package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.lfasr.concurrent.ConcurrentLockAspect;
import com.xbongbong.paas.business.rule.RuleBusinessLogger;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PlatFormEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.SaasParticularAttributePoJo;
import com.xbongbong.paas.help.FormDataValidateProductHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.pojo.ButtonPojo;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.WorkFlowPojo;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.FormDataGetVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CloneUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.businessdata.pojo.dto.FormatExplainDTO;
import com.xbongbong.pro.businessproduct.pojo.dto.BusinessProductListDTO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.detailtab.dto.ChangeDocumentStatusSaveDTO;
import com.xbongbong.pro.detailtab.vo.ChangeDocumentStatusSaveVO;
import com.xbongbong.pro.detailtab.vo.ProductSummaryVO;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ImportErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.InstockErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.OutstockErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProductErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SettleAccountErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.WarehouseErrorCodeEnum;
import com.xbongbong.pro.listbatch.pojo.dto.AddLabelDTO;
import com.xbongbong.pro.log.pojo.dto.RuleBusinessLogDTO;
import com.xbongbong.pro.product.pojo.ProductSavePojo;
import com.xbongbong.pro.product.pojo.dto.PagingProductDTO;
import com.xbongbong.pro.product.pojo.dto.ProductStockInfoSaveDTO;
import com.xbongbong.pro.product.pojo.vo.DetailProductVO;
import com.xbongbong.pro.product.pojo.vo.PagingProductVO;
import com.xbongbong.pro.productbaseinfo.pojo.dto.ProductBaseInfoDeleteBatchDTO;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.transfer.pojo.dto.TransferDeleteBatchDTO;
import com.xbongbong.pro.transfer.pojo.dto.TransferEditAttrUpdateDTO;
import com.xbongbong.pro.transfer.pojo.dto.TransferResetInstockIdDTO;
import com.xbongbong.pro.transfer.pojo.dto.TransferUpdateBatchDTO;
import com.xbongbong.pro.transfer.pojo.dto.TransferUpdateByBusinessRuleDTO;
import com.xbongbong.pro.transfer.pojo.dto.TransferUpdateDTO;
import com.xbongbong.pro.transfer.pojo.vo.TransferDeleteBatchVO;
import com.xbongbong.pro.transfer.pojo.vo.TransferResetInstockIdVO;
import com.xbongbong.pro.transferproduct.pojo.dto.FormatTransferProductDTO;
import com.xbongbong.pro.transferproduct.pojo.dto.TransferProductDeleteDTO;
import com.xbongbong.pro.transferproduct.pojo.dto.TransferProductListDTO;
import com.xbongbong.pro.transferproduct.pojo.vo.TransferProductListVO;
import com.xbongbong.saas.analytical.impl.TransferValidateAnalyticalServiceImpl;
import com.xbongbong.saas.annotation.BusinessTypeToServiceAnnotation;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductBaseInfoEntity;
import com.xbongbong.saas.domain.entity.ProductSerialBalanceEntity;
import com.xbongbong.saas.domain.entity.ProductSerialFlowEntity;
import com.xbongbong.saas.domain.entity.ProductStockEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.SettleAccountsEntity;
import com.xbongbong.saas.domain.entity.TransferProductEntity;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.TransferEntityExt;
import com.xbongbong.saas.domain.entity.ext.TransferProductEntityExt;
import com.xbongbong.saas.enums.BusinessProductEnum;
import com.xbongbong.saas.enums.BusinessTypeToServiceEnum;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.InOutStockStatusEnum;
import com.xbongbong.saas.enums.InstockTypeEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperatePageEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.RelativeProductEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.UpdateDataTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.SerialEnum;
import com.xbongbong.saas.enums.business.SerialStatusEnum;
import com.xbongbong.saas.enums.business.TransferEnum;
import com.xbongbong.saas.enums.dictionary.AllInBoundEnum;
import com.xbongbong.saas.enums.dictionary.EnableButtonEnum;
import com.xbongbong.saas.enums.dictionary.TransferNewStatusEnum;
import com.xbongbong.saas.enums.dictionary.TransferStatusEnum;
import com.xbongbong.saas.enums.dictionary.TransferTypeEnum;
import com.xbongbong.saas.enums.product.AssembleProductEnum;
import com.xbongbong.saas.enums.product.TransferProductEnum;
import com.xbongbong.saas.enums.subform.ProductStockSubFormEnum;
import com.xbongbong.saas.enums.subform.ProductWarehouseSubFormEnum;
import com.xbongbong.saas.help.BatchSeqExplainHelp;
import com.xbongbong.saas.help.DefaultAttrHelp;
import com.xbongbong.saas.help.ExplainHelp;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.help.ProDetailHandlerHelp;
import com.xbongbong.saas.help.RelativeProductHelp;
import com.xbongbong.saas.help.SaasUpdateHelp;
import com.xbongbong.saas.help.workflow.ProductSerialHelp;
import com.xbongbong.saas.help.workflow.TransferHelp;
import com.xbongbong.saas.model.ProductBaseInfoModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductSerialBalanceModel;
import com.xbongbong.saas.model.ProductSerialFlowModel;
import com.xbongbong.saas.model.ProductStockModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.SettleAccountsModel;
import com.xbongbong.saas.model.SpecificationModel;
import com.xbongbong.saas.model.TransferModel;
import com.xbongbong.saas.model.TransferProductModel;
import com.xbongbong.saas.model.TransferProductService;
import com.xbongbong.saas.service.FormatSpecialBusinessService;
import com.xbongbong.saas.service.InstockService;
import com.xbongbong.saas.service.MobileDetailService;
import com.xbongbong.saas.service.OutstockService;
import com.xbongbong.saas.service.ProductBaseInfoService;
import com.xbongbong.saas.service.ProductSerialService;
import com.xbongbong.saas.service.TransferService;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static com.xbongbong.saas.enums.RelativeProductEnum.BARCODE;
import static com.xbongbong.saas.enums.RelativeProductEnum.BATCH;
import static com.xbongbong.saas.enums.RelativeProductEnum.GUARANTEE_PERIOD;
import static com.xbongbong.saas.enums.RelativeProductEnum.MEMO;
import static com.xbongbong.saas.enums.RelativeProductEnum.NAME;
import static com.xbongbong.saas.enums.RelativeProductEnum.NUM;
import static com.xbongbong.saas.enums.RelativeProductEnum.PRODUCE_DATE;
import static com.xbongbong.saas.enums.RelativeProductEnum.PRODUCT_NO;
import static com.xbongbong.saas.enums.RelativeProductEnum.SPECIFICATION;
import static com.xbongbong.saas.enums.RelativeProductEnum.STOCK;
import static com.xbongbong.saas.enums.RelativeProductEnum.UNIT;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author feng.zheng
 * @version v1.0
 * @date 2019/2/15 15:25
 * @since v1.0
 */
@Service("transferService")
@BusinessTypeToServiceAnnotation(businessService = BusinessTypeToServiceEnum.TRANSFER)
public class TransferServiceImpl implements TransferService, FormatSpecialBusinessService {

    private static final Logger LOG = LoggerFactory.getLogger(TransferServiceImpl.class);

    @Resource
    private DefaultAttrHelp defaultAttrHelp;
    @Resource
    private SaasUpdateHelp saasUpdateHelp;
    @Resource
    private ExplainHelp explainHelp;
    @Resource
    private TransferModel transferModel;
    @Resource
    private TransferProductService transferProductService;
    @Resource
    private ProductBaseInfoService productBaseInfoService;
    @Resource
    private ProductModel productModel;
    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private TransferProductModel transferProductModel;
    @Resource
    private ProductBaseInfoModel productBaseInfoModel;
    @Resource
    private SpecificationModel specificationModel;
    @Resource
    private OutstockService outstockService;
    @Resource
    private InstockService instockService;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private ProductStockModel productStockModel;
    @Resource
    private ProductServiceImpl productService;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    @Lazy
    private RuleBusinessLogger ruleBusinessLogger;
    @Resource
    private FormDataValidateProductHelp formDataValidateProductHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private MobileDetailService mobileDetailService;
    @Resource
    private ProDetailHandlerHelp proDetailHandlerHelp;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private ProductSerialBalanceModel productSerialBalanceModel;
    @Resource
    private ProductSerialFlowModel productSerialFlowModel;
    @Resource
    private ProductSerialService productSerialService;
    @Resource
    private RelativeProductHelp relativeProductHelp;
    @Resource
    private LogHelp logHelp;
    @Resource
    private LogHandleHelp logHandleHelp;
    @Resource
    private TransferValidateAnalyticalServiceImpl transferAnalyticalService;
    @Resource
    private TransferHelp transferHelp;
    @Resource
    private ConcurrentLockAspect concurrentLockAspect;
    @Resource
    private SettleAccountsModel settleAccountsModel;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private ProductSerialHelp productSerialHelp;

    /**
     * 调拨单保存前saas特殊校验
     *
     * @param validateDataDTO saas特殊校验数据入参
     * @throws XbbException 业务异常
     * @author feng.zheng
     * @date 2019/1/18
     */
    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        transferAnalyticalService.beforeSave(validateDataDTO);
    }

    /**
     * 校验产品
     *
     * @param productArray   产品arr
     * @param corpid         公司id
     * @param outWarehouseId 仓库id
     * @throws XbbException 异常
     */
    private void checkProduct(JSONArray productArray, String corpid, Long outWarehouseId, String warehouseName) throws XbbException {
        List<Long> productIds = new ArrayList<>();
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject productObj = productArray.getJSONObject(i);
            Long productId = productObj.getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
            productIds.add(productId);
            // 产品数量校验
            String productNumStr = productObj.getString(StringConstant.NUM);
            if (!StringUtil.isDigital(productNumStr)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028.getCode(), ErrorMessageConstant.PRODUCT_NUM_ONLY_NUM);
            }
            Double productNum = Double.valueOf(productNumStr);
            if (productNum <= BasicConstant.ZERO) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028.getCode(), ErrorMessageConstant.PRODUCT_NUM_OVER_ZERO);
            }
        }
        Map<Long, ProductEntityExt> productMap = productModel.getProductMapByIdIn(corpid, productIds, null);
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("productIdIn", productIds);
        param.put("warehouseChecked", BasicConstant.ONE);
        List<ProductWarehouseEntity> productWarehouseList = productWarehouseModel.findEntitysWithWarehouseChecked(param,1);
//        List<ProductStockInfoEntity> productStockInfoList = productStockInfoService.getValidBatchInfoList(corpid, param);
        // 需要查询的字段
        List<String> fieldList = new ArrayList<>();
        fieldList.add(ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.BATCH));
        fieldList.add(ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.PARENT_ID));
        fieldList.add(ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.NUM));
        fieldList.add(ProductStockSubFormEnum.getAttrConnectData(ProductStockSubFormEnum.WAREHOUSE_ID));
        List<ProductStockEntity> productStockEntityList = productStockModel.getValidBatchInfoList(productIds,corpid,null,null, fieldList);
        StringBuilder productNotInWarehouse = new StringBuilder();
        // 产品是否在出库仓库中
        boolean inWarehouse = false;
        StringBuilder productOverStock = new StringBuilder();
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject productObj = productArray.getJSONObject(i);
            Long productId = productObj.getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
            Double productNum = productObj.getDouble(StringConstant.NUM);
            String batch = productObj.getString(StringConstant.BATCH);
            ProductEntityExt productEntity = productMap.get(productId);
            // 产品是否存在
            if (productEntity == null) {
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205025);
            }
            if (Objects.equals(productEntity.getDel(), DelEnum.DELETE.getDel())) {
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205018);
            }
            String productName = FastJsonHelper.getStringOrDefaultFromFormData(productEntity.getData(), ProductEnum.NAME.getAttr(), "");
            for (ProductWarehouseEntity productWarehouse : productWarehouseList) {
                if (Objects.equals(productId, productWarehouse.getProductId()) &&
                        Objects.equals(outWarehouseId, productWarehouse.getWarehouseId())) {
                    inWarehouse = true;
                    if (Double.compare(productNum, productWarehouse.getNum()) > 0) {
                        // 调出数量超出产品分仓库存
                        productOverStock.append(productName).append(StringConstant.COMMA);
                    }
                }
            }
            if (!inWarehouse) {
                productNotInWarehouse.append(productName).append(StringConstant.COMMA);
            }
            if (StringUtil.isNotEmpty(batch) && productStockEntityList.size() > 0) {
                Double differNum = 0.0;
                for (ProductStockEntity productStockInfo : productStockEntityList) {
                    if (Objects.equals(productId, productStockInfo.getProductId()) &&
                            Objects.equals(outWarehouseId, productStockInfo.getWarehouseId()) &&
                            Objects.equals(batch, productStockInfo.getBatch())) {
                        // 调出数量超出批次库存
                        differNum += productStockInfo.getNum();
                    }
                }

                if (Double.compare(productNum, differNum) > BasicConstant.ZERO) {
                    productOverStock.append(String.format(I18nMessageUtil.getMessage(ErrorMessageConstant.BATCH_PRODUCT), batch, productName));
                }
            }
        }
        String productWarehouseStr = productNotInWarehouse.toString();
        if (productWarehouseStr.length() > BasicConstant.ZERO) {
            productWarehouseStr = productWarehouseStr.substring(BasicConstant.ZERO, productWarehouseStr.length() - BasicConstant.ONE);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028.getCode(), ErrorMessageConstant.PRODUCT_NOT_IN_OUT_WAREHOUSE, productWarehouseStr, warehouseName);
        }
        String productStock = productOverStock.toString();
        if (productStock.length() > 0) {
            productStock = productStock.substring(0, productStock.length() - 1);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028.getCode(), ErrorMessageConstant.OUT_NUM_OVER_STOCK_NUM, productStock, warehouseName);
        }
    }


    /**
     * 调拨单保存后逻辑
     *
     * @param saasFormSaveDTO saas保存数据
     * @throws XbbException 业务异常
     * @author feng.zheng
     */
    @Override
    public void afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        String corpid = saasFormSaveDTO.getCorpid();
        Long id = saasFormSaveDTO.getNewPaasFormDataEntity().getId();
        JSONObject newData = saasFormSaveDTO.getNewData();
        String transferType = FastJsonHelper.getStringOrDefaultFromFormData(newData, TransferEnum.TRANSFER_TYPE.getAttr(), TransferTypeEnum.UNLOCAL_TRANSFER.getCode());
        JSONArray productArray = newData.getJSONArray(TransferEnum.PRODUCTS.getAttr());
        Long intoWarehouseId = FastJsonHelper.getLongOrDefaultFromFormData(newData, TransferEnum.INTO_WAREHOUSE_ID.getAttr(), 0L);
        Long outWarehouseId = FastJsonHelper.getLongOrDefaultFromFormData(newData, TransferEnum.OUT_WAREHOUSE_ID.getAttr(), 0L);
        Long formId = saasFormSaveDTO.getNewPaasFormDataEntity().getFormId();
        Boolean productCanSee = saasFormSaveDTO.getSaasNeedRedundantAttrPoJo().getAttrCanSee(TransferEnum.PRODUCTS.getAttr());
        Boolean hasInOrOut = Objects.isNull(FastJsonHelper.getLongOrDefaultFromFormData(saasFormSaveDTO.getNewData(),TransferEnum.INSTOCK_ID.getAttr(),null)) || Objects.isNull(FastJsonHelper.getLongOrDefaultFromFormData(saasFormSaveDTO.getNewData(),TransferEnum.OUTSTOCK_ID.getAttr(),null));
        // 更新调拨单关联产品
        if (saasFormSaveDTO.getIsNew() || (productCanSee && !hasInOrOut)){
            saveProduct(saasFormSaveDTO.getCorpid(), id, intoWarehouseId, outWarehouseId, productArray, formId, saasFormSaveDTO.getIsNew());
        }
        //新建本地调拨走下面的逻辑
        if (saasFormSaveDTO.getIsNew() && Objects.equals(transferType, TransferTypeEnum.LOCAL_TRANSFER.getCode())) {
            // 本地调拨出入库的关联产品取调拨单出库仓库的产品
            Map<Object,Double> costMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Object,Double> stockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            formDataValidateProductHelp.getSkuWarehouseOrBatchCost(productArray, outWarehouseId, saasFormSaveDTO.getCorpid(), costMap, stockMap);
            boolean isCheck = concurrentLockAspect.checkStock(corpid);
            if (isCheck){
                // 没开启负库存的才超发出库校验
                concurrentLockAspect.checkTransferStock(corpid,productArray,intoWarehouseId,outWarehouseId,stockMap);
            }
            saasFormSaveDTO.setCostMap(costMap);
            SaasFormSaveDTO saasFormSaveDT1 = (SaasFormSaveDTO) CloneUtil.deepClone(saasFormSaveDTO);
            Runnable runnable = () -> {
                boolean isInstock = false;
                boolean isOutstock = false;
                try {
                    // 生成出库单
                    isOutstock = true;
                    outstockService.generateOutStockSheet(saasFormSaveDTO);
                    // 生成入库单
                    isInstock = true;
                    instockService.generateInStockSheet(saasFormSaveDT1);
                } catch (Exception e) {
                    if (isCheck){
                        // 没开启负库存的才需要回滚
                        concurrentLockAspect.transferOnstockRollBack(intoWarehouseId, outWarehouseId, stockMap, isInstock, isOutstock);
                    }
                    LOG.error("TransferServiceImpl.afterSave.generateStockSheet 执行出错：", e);
                }
            };
            threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
        }
    }

    private void saveSerial(TransferProductEntity transferProductEntity, JSONObject productData) throws XbbException {
        String corpid = transferProductEntity.getCorpid();
        // 调拨单id
        Long transferId = transferProductEntity.getTransferId();
        TransferEntityExt transferEntityExt = transferModel.getByKey(transferId, corpid);
        JSONObject transferEntityExtData = transferEntityExt.getData();

        // 编辑新增产品
        List<ProductSerialFlowEntity> flowEntityList = productSerialFlowModel.getFlowByRefIdAndBusiness(Collections.singletonList(transferId), XbbRefTypeEnum.TRANSFER.getCode(), corpid);
        List<String> serialList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (CollectionUtils.isNotEmpty(flowEntityList)) {
            flowEntityList.forEach(item -> serialList.add(item.getSeqKey()));
        }

        Set<String> seqKeyList = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<ProductSerialFlowEntity> productSerialFlowEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, ProductSerialFlowEntity> productSerialFlowEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Long productId = productData.getLong(SelectProductEnum.PRODUCT.getAttr());
        JSONArray seqArray = productData.getJSONArray(ProductConstant.SEQ);
        if (BasicConstant.ZERO.equals(productData.getIntValue(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr())) && (Objects.isNull(seqArray) || seqArray.isEmpty())) {
            return;
        }
        for (int j = 0; j < seqArray.size(); j++) {
            JSONObject seqData = seqArray.getJSONObject(j);
            String serial = seqData.getString(SerialEnum.SERIAL.getAttr());
            String seqKey = productId + "_" + serial;
            if (serialList.contains(seqKey)) {
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205094, String.format(ProductErrorCodeEnum.API_ERROR_205094.getMsg(), serial));
            }
            ProductSerialFlowEntity productSerialFlowEntity = new ProductSerialFlowEntity();
            productSerialFlowEntity.setCorpid(corpid);
            productSerialFlowEntity.setProductId(productId);
            productSerialFlowEntity.setSeq(serial);
            productSerialFlowEntity.setMemo(seqData.getString(SerialEnum.MEMO.getAttr()));
            productSerialFlowEntity.setStatus(SerialStatusEnum.IN_STOCK.getCode());
            productSerialFlowEntity.setDate(DateTimeUtil.getInt());
            productSerialFlowEntity.setBusinessType(XbbRefTypeEnum.TRANSFER.getCode());
            productSerialFlowEntity.setRefId(transferId);
            productSerialFlowEntity.setRefSheetNo(transferEntityExt.getSerialNo());
            // 关联产品id
            productSerialFlowEntity.setRefProductId(transferProductEntity.getId());
            productSerialFlowEntity.setParentId(transferProductEntity.getParentId());
            // 调拨出入库仓库数据
            productSerialFlowEntity.setWarehouseId(transferEntityExtData.getLong(TransferEnum.OUT_WAREHOUSE_ID.getAttr()));
            productSerialFlowEntity.setWarehouseName(transferEntityExtData.getString(TransferEnum.OUT_WAREHOUSE_ID_LINKED_TEXT.getAttr()));
            productSerialFlowEntity.setSeqKey(seqKey);
            productSerialFlowEntity.setDel(BasicConstant.ZERO);

            seqKeyList.add(productSerialFlowEntity.getSeqKey());
            productSerialFlowEntityList.add(productSerialFlowEntity);
            productSerialFlowEntityMap.put(productSerialFlowEntity.getSeqKey(), productSerialFlowEntity);
        }
        if (CollectionUtils.isNotEmpty(productSerialFlowEntityList)) {
            Map<String, Object> param = new HashMap<>();
            param.put("corpid", corpid);
            param.put("seqKeyIn", seqKeyList);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<ProductSerialBalanceEntity> entitys = productSerialBalanceModel.findEntitys(param);
            for (ProductSerialBalanceEntity entity : entitys) {
                ProductSerialFlowEntity productSerialFlowEntity = productSerialFlowEntityMap.get(entity.getSeqKey());
                entity.setStatus(productSerialFlowEntity.getStatus());
                entity.setBusinessType(productSerialFlowEntity.getBusinessType());
                entity.setRefId(productSerialFlowEntity.getRefId());
                entity.setRefSheetNo(productSerialFlowEntity.getRefSheetNo());
                entity.setRefProductId(productSerialFlowEntity.getRefProductId());
                entity.setDate(productSerialFlowEntity.getDate());

                productSerialFlowEntity.setWarehouseId(entity.getWarehouseId());
                productSerialFlowEntity.setBusinessId(entity.getBusinessId());
                productSerialFlowEntity.setBusinessName(entity.getBusinessName());
            }
            try {
                productSerialBalanceModel.updateBatch(entitys, corpid);
                productSerialFlowModel.insertBatch(productSerialFlowEntityList);
            } catch (Exception e) {
                LOG.error("Failed to save the serial number，corpid = " + corpid + ",dataId=" + transferId);
                e.printStackTrace();
            }

        }
    }

    /**
     * 保存产品
     *  @param corpid          公司id
     * @param transferId      调拨单id
     * @param intoWarehouseId 入库id
     * @param outWarehouseId  出库id
     * @param productArray    产品
     * @param formId          表单id
     * @param isNew
     */
    private void saveProduct(String corpid, Long transferId, Long intoWarehouseId, Long outWarehouseId, JSONArray productArray, Long formId, Boolean isNew) throws XbbException {
        Map<Long, TransferProductEntity> orginProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, ProductBaseInfoEntity> orginProductBaseInfoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (!isNew) {
            //非新建情况下，取得调拨单编辑前的关联产品
            List<TransferProductEntity> transferProductEntityList = transferProductModel.getProductsByTransferId(transferId,corpid);
            List<Long> refProductIdList = new ArrayList<>(transferProductEntityList.size());
            for (TransferProductEntity transferProductEntity : transferProductEntityList) {
                orginProductMap.put(transferProductEntity.getId(), transferProductEntity);
                refProductIdList.add(transferProductEntity.getId());
            }
            if (!refProductIdList.isEmpty()) {
                List<ProductBaseInfoEntity> productBaseInfoList = productBaseInfoModel.getProductBaseInfoList(corpid, XbbRefTypeEnum.TRANSFER_PRODUCT.getCode(), refProductIdList);
                productBaseInfoList.forEach(item -> orginProductBaseInfoMap.put(item.getRefId(), item));
            }
        }
        //新增产品
        List<TransferProductEntity> productAddList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //编辑产品
        List<TransferProductEntity> productUpdateList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid,productArray);
        List<ProductBaseInfoEntity> addProductBaseInfoList = new ArrayList<>();
        List<ProductBaseInfoEntity> updateProductBaseInfoList = new ArrayList<>();

        List<TransferProductEntity> insertProductList = new ArrayList<>();
        Map<Integer, JSONObject> inProductSeqMap = new HashMap<>(productArray.size());
        Map<Integer, ProductBaseInfoEntity> inProductBaseInfoMap = new HashMap<>(productArray.size());
        Integer sort = 0;
        Map<Integer, TransferProductEntity> insertProductMap = new HashMap<>(productArray.size());
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            JSONArray seqArray = jsonObject.getJSONArray(ProductConstant.SEQ);
            int enableSerialNumber = jsonObject.getIntValue(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr());
            // 移除序列号相关数据，不存入关联产品数据中
            jsonObject.remove(ProductConstant.SEQ);
            jsonObject.remove(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr());
            jsonObject.remove(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getSaasAttr());

            Long pageProductId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            Long businessProductId = jsonObject.getLong(BusinessConstant.PRODUCT_SUB_ID);
            Double productNum = jsonObject.getDouble(TransferProductEnum.NUM.getAttr());
            String memo = jsonObject.getString(TransferProductEnum.MEMO.getAttr());
            boolean addProductFlag = formDataValidateProductHelp.addProductFlag(businessProductId);
            TransferProductEntity transferProductEntity;
            if (addProductFlag) {
                //新增产品
                transferProductEntity = new TransferProductEntity();
//                productAddList.add(transferProductEntity);
//                productBaseInfoEntity = new ProductBaseInfoEntity();
            } else if (orginProductMap.containsKey(businessProductId)) {
                //编辑产品
                transferProductEntity = orginProductMap.get(businessProductId);
                productUpdateList.add(transferProductEntity);
                //只剩删除的产品
                orginProductMap.remove(businessProductId);
            } else {
                //删除产品
                continue;
            }
            JSONObject productData = productMap.get(pageProductId).getData();
            transferProductEntity.setParentId(productData.getLong(ProductEnum.PARENT_ID.getAttr()));
            transferProductEntity.setProductId(pageProductId);
            transferProductEntity.setProductNum(productNum);
            transferProductEntity.setCorpid(corpid);
            transferProductEntity.setIntoWarehouseId(intoWarehouseId);
            transferProductEntity.setOutWarehouseId(outWarehouseId);
            transferProductEntity.setTransferId(transferId);
            transferProductEntity.setFormId(formId);
            transferProductEntity.setProductName(productData.getString(ProductEnum.NAME.getAttr()));
            transferProductEntity.setProductNo(productData.getString(ProductEnum.PRODUCT_NO.getAttr()));
            transferProductEntity.setProductSpecification(productData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
            Integer enableMultiUnit = productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
            if (Objects.equals(enableMultiUnit, 1)) {
                formDataValidateProductHelp.setBusinessUnit(jsonObject, transferProductEntity);
                transferProductEntity.setProductUnit(jsonObject.getString(SelectProductEnum.UNIT.getAttr()));
            } else {
                transferProductEntity.setProductUnit(productData.getString(ProductEnum.UNIT.getAttr()));
                jsonObject.put(TransferProductEnum.UNIT.getAttr(), productData.getString(ProductEnum.UNIT.getAttr()));
            }
            transferProductEntity.setProductPrice(productData.getDouble(ProductEnum.PRICE.getAttr()));
            transferProductEntity.setBatch(jsonObject.getString(TransferProductEnum.BATCH.getAttr()));
            transferProductEntity.setProduceDate(jsonObject.getLong(AssembleProductEnum.PRODUCE_DATE.getAttr()));
            if (Objects.nonNull(jsonObject.getLong(TransferProductEnum.GUARANTEE_PERIOD.getAttr()))){
                transferProductEntity.setGuaranteePeriod(jsonObject.getLong(TransferProductEnum.GUARANTEE_PERIOD.getAttr()) * TimeConstant.SECONDS_PER_DAY);
            }
            transferProductEntity.setUpdateTime(DateTimeUtil.getInt());
            transferProductEntity.setMemo(memo);
//            setLatestParam(transferProduct, parentProductMap, id, productMap);
            transferProductEntity.setSort(sort);
            transferProductEntity.setData(jsonObject);
            JSONObject productBaseInfoData = new JSONObject();
            if (addProductFlag) {
                insertProductList.add(transferProductEntity);
                insertProductMap.put(i, transferProductEntity);
                // 生成出入库单，会用到这个属性
//                jsonObject.put(BusinessConstant.REF_PRODUCT_ID, transferProductEntity.getId());
                if (Objects.nonNull(transferProductEntity.getBusinessUnit())) {
                    productBaseInfoData.put(SelectProductEnum.BUSINESS_UNIT.getAttr(), transferProductEntity.getBusinessUnit());
                    productBaseInfoData.put(SelectProductEnum.RATE.getAttr(), transferProductEntity.getRate());
                    productBaseInfoData.put(SelectProductEnum.UNIT_GROUP.getAttr(), transferProductEntity.getGroupId());
                    productBaseInfoData.put(SelectProductEnum.BUSINESS_NUM.getAttr(), transferProductEntity.getBusinessNum());
                }
                // 新增序列号，关联产品不保存序列号，但是后面序列号保存以及生成出入库单需要序列号数据，所以给他加回去
                if (Objects.nonNull(seqArray) && !seqArray.isEmpty()) {
                    productBaseInfoData.put(ProductConstant.SEQ, seqArray);
                    productBaseInfoData.put(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr(), enableSerialNumber);
                    JSONObject seqJson = new JSONObject();
                    seqJson.put(ProductConstant.SEQ, seqArray);
                    seqJson.put(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr(), enableSerialNumber);
                    inProductSeqMap.put(i, seqJson);
                }
                productAddList.add(transferProductEntity);
            }
            //额外信息
            if (StringUtil.isNotEmpty(jsonObject.getString(TransferProductEnum.BATCH.getAttr())) && !orginProductBaseInfoMap.containsKey(transferProductEntity.getId())) {
                ProductBaseInfoEntity productBaseInfoEntity = new ProductBaseInfoEntity();
                productBaseInfoData.putAll(jsonObject);
                productBaseInfoEntity.setCorpid(corpid);
                productBaseInfoEntity.setFormId(formId);
                productBaseInfoEntity.setRefId(transferProductEntity.getId());
                productBaseInfoEntity.setRefType(XbbRefTypeEnum.TRANSFER_PRODUCT.getCode());
                productBaseInfoEntity.setBatch(jsonObject.getString(TransferProductEnum.BATCH.getAttr()));
                productBaseInfoEntity.setProduceDate(jsonObject.getLong(AssembleProductEnum.PRODUCE_DATE.getAttr()));
                if (Objects.nonNull(jsonObject.getLong(TransferProductEnum.GUARANTEE_PERIOD.getAttr()))){
                    productBaseInfoEntity.setGuaranteePeriod(jsonObject.getLong(TransferProductEnum.GUARANTEE_PERIOD.getAttr()) * TimeConstant.SECONDS_PER_DAY);
                }
                productBaseInfoEntity.setMemo(jsonObject.getString(TransferProductEnum.MEMO.getAttr()));
                productBaseInfoEntity.setData(productBaseInfoData);
                productBaseInfoEntity.setDel(0);
                productBaseInfoEntity.setAddTime(DateTimeUtil.getInt());
                productBaseInfoEntity.setUpdateTime(DateTimeUtil.getInt());
                inProductBaseInfoMap.put(i, productBaseInfoEntity);
            } else if (!addProductFlag && orginProductBaseInfoMap.containsKey(transferProductEntity.getId())) {
                ProductBaseInfoEntity productBaseInfoEntity = orginProductBaseInfoMap.get(transferProductEntity.getId());
                productBaseInfoEntity.setBatch(jsonObject.getString(TransferProductEnum.BATCH.getAttr()));
                productBaseInfoEntity.setProduceDate(jsonObject.getLong(AssembleProductEnum.PRODUCE_DATE.getAttr()));
                if (Objects.nonNull(jsonObject.getLong(TransferProductEnum.GUARANTEE_PERIOD.getAttr()))){
                    productBaseInfoEntity.setGuaranteePeriod(jsonObject.getLong(TransferProductEnum.GUARANTEE_PERIOD.getAttr()) * TimeConstant.SECONDS_PER_DAY);
                }
                productBaseInfoEntity.setMemo(jsonObject.getString(TransferProductEnum.MEMO.getAttr()));
                updateProductBaseInfoList.add(productBaseInfoEntity);
                orginProductBaseInfoMap.remove(transferProductEntity.getId());
            }
            sort++;
        }

        transferProductModel.insertBatch(insertProductList);
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            Long id = jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID);
            if (insertProductMap.containsKey(i)) {
                id = insertProductMap.get(i).getId();
                jsonObject.put(BusinessConstant.REF_PRODUCT_ID, id);
            }
            if (inProductSeqMap.containsKey(i)) {
                jsonObject.put(ProductConstant.SEQ, inProductSeqMap.get(i).get(ProductConstant.SEQ));
                jsonObject.put(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr(), inProductSeqMap.get(i).get(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr()));
            }
            if (inProductBaseInfoMap.containsKey(i)) {
                ProductBaseInfoEntity productBaseInfoEntity = inProductBaseInfoMap.get(i);
                productBaseInfoEntity.setRefId(id);
                productBaseInfoEntity.getData().put(BusinessConstant.REF_PRODUCT_ID, id);
                inProductBaseInfoMap.put(i, productBaseInfoEntity);
            }
        }
        inProductBaseInfoMap.forEach((key, value)->{
            addProductBaseInfoList.add(value);
        });

        if (!addProductBaseInfoList.isEmpty()){
            productBaseInfoModel.insertBatch(addProductBaseInfoList);
        }
        if (!updateProductBaseInfoList.isEmpty()){
            // TODO
            productBaseInfoModel.updateBatch(updateProductBaseInfoList, corpid);
        }
        // 更新产品
        transferProductModel.updateMulti(productUpdateList, corpid);
        List<Long> delRefIdList = new ArrayList<>();
        for (Map.Entry<Long, TransferProductEntity> entry : orginProductMap.entrySet()) {
            TransferProductEntity delProduct = entry.getValue();
            delRefIdList.add(delProduct.getId());
        }
        // 删除序列号
        productSerialFlowModel.deleteByRefProductId(corpid, transferId, delRefIdList, XbbRefTypeEnum.TRANSFER.getCode());

        productSerialBalanceModel.deleteBatchByRefProductId(Collections.singletonList(transferId), corpid, XbbRefTypeEnum.TRANSFER.getCode(), delRefIdList);
        // 删除调拨产品
        transferProductModel.deleteBatch(delRefIdList, corpid, DelEnum.DELETE.getDel());
        if (!delRefIdList.isEmpty()){
            productBaseInfoModel.deleteByRefIds(corpid,delRefIdList,XbbRefTypeEnum.TRANSFER_PRODUCT.getCode());
        }

        for (TransferProductEntity addProduct : productAddList) {
            saveSerial(addProduct, addProduct.getData());
        }

    }

    /**
     * 保存产品
     *  @param corpid          公司id
     * @param transferId      调拨单id
     * @param intoWarehouseId 入库id
     * @param outWarehouseId  出库id
     * @param productArray    产品
     * @param formId          表单id
     * @param isNew
     */
    private void saveProductForWorkflow(String corpid, Long transferId, Long intoWarehouseId, Long outWarehouseId, JSONArray productArray, Long formId, Boolean isNew) throws XbbException {
        Map<Long, TransferProductEntity> originProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (!isNew) {
            //非新建情况下，取得调拨单编辑前的关联产品
            List<TransferProductEntity> transferProductEntityList = transferProductModel.getProductsByTransferId(transferId,corpid, Arrays.asList(DelEnum.NORMAL.getDel(), DelEnum.APPROVE_FAILED.getDel()));
            for (TransferProductEntity transferProductEntity : transferProductEntityList) {
                originProductMap.put(transferProductEntity.getId(), transferProductEntity);

            }
        }
        //编辑产品
        List<TransferProductEntity> productUpdateList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Integer, TransferProductEntity> productInsertMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<TransferProductEntity> productInsertList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Integer, JSONObject> inProductSeqMap = new HashMap<>(productArray.size());
        Map<Integer, JSONObject> inProductBaseInfoMap = new HashMap<>(productArray.size());
        Map<Long, PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid,productArray);
        Integer sort = 0;
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            JSONArray seqArray = jsonObject.getJSONArray(ProductConstant.SEQ);
            int enableSerialNumber = jsonObject.getIntValue(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr());
            // 移除序列号相关数据，不存入关联产品数据中
            jsonObject.remove(ProductConstant.SEQ);
            jsonObject.remove(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr());
            jsonObject.remove(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getSaasAttr());

            Long pageProductId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            Long businessProductId = jsonObject.getLong(BusinessConstant.PRODUCT_SUB_ID);
            Double productNum = jsonObject.getDouble(TransferProductEnum.NUM.getAttr());
            String memo = jsonObject.getString(TransferProductEnum.MEMO.getAttr());
            boolean addProductFlag = formDataValidateProductHelp.addProductFlag(businessProductId);
            TransferProductEntity transferProductEntity;
            if (addProductFlag) {
                //新增产品
                transferProductEntity = new TransferProductEntity();
            } else if (originProductMap.containsKey(businessProductId)) {
                //编辑产品
                transferProductEntity = originProductMap.get(businessProductId);
                if (Objects.equals(DelEnum.APPROVE_FAILED.getDel(), transferProductEntity.getDel())) {
                    transferProductEntity.setDel(DelEnum.NORMAL.getDel());
                }
                productUpdateList.add(transferProductEntity);
                //只剩删除的产品
                originProductMap.remove(businessProductId);
            } else {
                //删除产品
                continue;
            }
            JSONObject productData = productMap.get(pageProductId).getData();
            transferProductEntity.setParentId(productData.getLong(ProductEnum.PARENT_ID.getAttr()));
            transferProductEntity.setProductId(pageProductId);
            transferProductEntity.setProductNum(productNum);
            transferProductEntity.setCorpid(corpid);
            transferProductEntity.setIntoWarehouseId(intoWarehouseId);
            transferProductEntity.setOutWarehouseId(outWarehouseId);
            transferProductEntity.setTransferId(transferId);
            transferProductEntity.setFormId(formId);
            transferProductEntity.setProductName(productData.getString(ProductEnum.NAME.getAttr()));
            transferProductEntity.setProductNo(productData.getString(ProductEnum.PRODUCT_NO.getAttr()));
            transferProductEntity.setProductSpecification(productData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
            Integer enableMultiUnit = productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
            if (Objects.equals(enableMultiUnit, 1)) {
                formDataValidateProductHelp.setBusinessUnit(jsonObject, transferProductEntity);
                transferProductEntity.setProductUnit(jsonObject.getString(SelectProductEnum.UNIT.getAttr()));
            } else {
                transferProductEntity.setProductUnit(productData.getString(ProductEnum.UNIT.getAttr()));
                jsonObject.put(TransferProductEnum.UNIT.getAttr(), productData.getString(ProductEnum.UNIT.getAttr()));
            }
            transferProductEntity.setProductPrice(productData.getDouble(ProductEnum.PRICE.getAttr()));
            transferProductEntity.setBatch(jsonObject.getString(TransferProductEnum.BATCH.getAttr()));
            transferProductEntity.setProduceDate(jsonObject.getLong(AssembleProductEnum.PRODUCE_DATE.getAttr()));
            if (Objects.nonNull(jsonObject.getLong(TransferProductEnum.GUARANTEE_PERIOD.getAttr()))){
                transferProductEntity.setGuaranteePeriod(jsonObject.getLong(TransferProductEnum.GUARANTEE_PERIOD.getAttr()) * TimeConstant.SECONDS_PER_DAY);
            }
            transferProductEntity.setUpdateTime(DateTimeUtil.getInt());
            transferProductEntity.setMemo(memo);
            transferProductEntity.setSort(sort);
            transferProductEntity.setData(jsonObject);
            if (addProductFlag) {
                productInsertList.add(transferProductEntity);
                productInsertMap.put(i, transferProductEntity);

                // 新增序列号，关联产品不保存序列号，但是后面序列号保存以及生成出入库单需要序列号数据，所以给他加回去
                if (Objects.nonNull(seqArray) && !seqArray.isEmpty()) {
                    JSONObject seqJson = new JSONObject();
                    seqJson.put(ProductConstant.SEQ, seqArray);
                    seqJson.put(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr(), enableSerialNumber);
                    inProductSeqMap.put(i, seqJson);
                }
            }
            sort++;
        }

        transferProductModel.insertBatch(productInsertList);
        productInsertMap.forEach((i, transferProductEntity)->{
            JSONObject jsonObject = productArray.getJSONObject(i);
            Long id = transferProductEntity.getId();
            jsonObject.put(BusinessConstant.REF_PRODUCT_ID, id);
            jsonObject.put(BusinessConstant.PRODUCT_SUB_ID, id);
            if (inProductSeqMap.containsKey(i)) {
                jsonObject.put(ProductConstant.SEQ, inProductSeqMap.get(i).get(ProductConstant.SEQ));
                jsonObject.put(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr(), inProductSeqMap.get(i).get(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr()));
            }
        });

        transferProductModel.updateMulti(productUpdateList, corpid);
        List<Long> deleteIdIn = new ArrayList<>();
        for (Map.Entry<Long, TransferProductEntity> entry : originProductMap.entrySet()) {
            TransferProductEntity delProduct = entry.getValue();
            deleteIdIn.add(delProduct.getId());
        }
        // 删除调拨产品
        transferProductModel.deleteBatch(deleteIdIn, corpid, DelEnum.DELETE.getDel());
    }

    /**
     * 保存产品基础信息
     *
     * @param corpid             公司id
     * @param refId              关联id
     * @param refType            关联类型
     * @param productJSON        产品
     * @param productName        产品名称
     * @param operateType        操作类型
     * @param isProductStockInfo 是否出入库
     * @throws XbbException 异常
     */
    private void saveProductBaseInfo(String corpid, Long refId, int refType, JSONObject productJSON, String productName, String operateType, Integer isProductStockInfo) throws XbbException {
        ProductStockInfoSaveDTO productStockInfoSaveDTO = new ProductStockInfoSaveDTO();
        productStockInfoSaveDTO.setCorpid(corpid);
        productStockInfoSaveDTO.setRefId(refId);
        productStockInfoSaveDTO.setRefType(refType);
        productStockInfoSaveDTO.setProductObj(productJSON);
        productStockInfoSaveDTO.setProductName(productName);
        productStockInfoSaveDTO.setOperateType(operateType);
        productStockInfoSaveDTO.setIsProductStockInfo(isProductStockInfo);
        productBaseInfoService.saveProductBaseInfo(productStockInfoSaveDTO);
    }

    /**
     * 返回调拨产品
     *
     * @param id               id
     * @param num              数量
     * @param corpid           公司id
     * @param intoWarehouseId  入库id
     * @param outWarehouseId   出库id
     * @param transferId       调拨单id
     * @param formId           表单id
     * @param sort             排序
     * @param parentProductMap 父产品
     * @param productMap       产品
     * @return 调拨单产品
     * @throws XbbException 异常
     */
    private TransferProductEntity buildTransferProduct(Long id, Double num, String corpid, Long intoWarehouseId, Long outWarehouseId, Long transferId, Long formId, Integer sort, Map<Long, ProductEntityExt> parentProductMap, Map<Long, ProductEntityExt> productMap) throws XbbException {
        TransferProductEntity transferProduct = new TransferProductEntity();
        transferProduct.setProductId(id);
        transferProduct.setProductNum(num);
        transferProduct.setCorpid(corpid);
        transferProduct.setIntoWarehouseId(intoWarehouseId);
        transferProduct.setOutWarehouseId(outWarehouseId);
        transferProduct.setTransferId(transferId);
        transferProduct.setFormId(formId);
        setLatestParam(transferProduct, parentProductMap, id, productMap);
        transferProduct.setSort(sort);
        transferProductModel.insert(transferProduct);
        return transferProduct;
    }

    /**
     * 更新调拨产品规格、名称等信息
     *
     * @param transferProductEntity 赋值盘点产品
     * @param parentProductMap      父产品
     * @param productMap            产品
     * @return 更新后的调拨单产品
     */
    private TransferProductEntity setLatestParam(TransferProductEntity transferProductEntity, Map<Long, ProductEntityExt> parentProductMap, Long id, Map<Long, ProductEntityExt> productMap) throws XbbException {
        ProductEntityExt product = productMap.getOrDefault(id, new ProductEntityExt());
        JSONObject productDataList = product.getData();
        // 获取父产品
        Long parentProductId = FastJsonHelper.getLongOrDefaultFromFormData(productDataList, ProductEnum.PARENT_ID.getAttr(), 0L);
        ProductEntityExt parentProduct = parentProductMap.getOrDefault(parentProductId, new ProductEntityExt());
        JSONObject parentProductDataList = parentProduct.getData();
        String specification = FastJsonHelper.getStringOrDefaultFromFormData(productDataList, ProductEnum.SPECIFICATION_LINK_TEXT.getAttr(), "{}");
        String name = FastJsonHelper.getStringOrDefaultFromFormData(productDataList, ProductEnum.NAME.getAttr(), "");
        String unit = FastJsonHelper.getStringOrDefaultFromFormData(productDataList, ProductEnum.UNIT.getAttr(), "");
        String productNo = FastJsonHelper.getStringOrDefaultFromFormData(parentProductDataList, ProductEnum.PRODUCT_NO.getAttr(), "");
        transferProductEntity.setParentId(parentProductId);
        transferProductEntity.setProductSpecification(specification);
        transferProductEntity.setProductName(name);
        transferProductEntity.setProductUnit(unit);
        transferProductEntity.setProductNo(productNo);
        return transferProductEntity;
    }



//    /**
//     * 获取调拨单产品列表
//     *
//     * @param businessProductListDTO 入参
//     * @param jsonObject 数据对象
//     * @return 产品
//     * @throws XbbException 异常
//     */
//    @Override
//    public BusinessProductListVO getTransferProductList(BusinessProductListDTO businessProductListDTO, JSONObject jsonObject) throws XbbException {
//        String corpid = businessProductListDTO.getCorpid();
//        String userId = businessProductListDTO.getUserId();
//        UserEntity userEntity = userModel.getByKey(userId, corpid);
//        Long transferId = businessProductListDTO.getDataId();
//        boolean detailGet = businessProductListDTO.getDetailGet();
//        Integer fromInstock = businessProductListDTO.getFromInstock();
//        Integer fromOutstock = businessProductListDTO.getFromOutstock();
//        boolean isInstock = Objects.equals(fromInstock, 1);
//        boolean isOutstock = Objects.equals(fromOutstock, 1);
//        boolean generalGetProduct = !isInstock && !isOutstock;
//
//        JSONObject transferDataList;
//        List<TransferProductEntity> transferProducts = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        List<ProductBaseInfoEntity> productBaseInfoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        modelMap.put(ParameterConstant.PAGE, businessProductListDTO.getPage());
//        modelMap.put(ParameterConstant.CORPID, corpid);
//        modelMap.put("transferId", transferId);
//        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
//        PageHelper pageHelper = PageHelperUtil.getPageHelper(modelMap, transferProductModel, businessProductListDTO.getPageSize());
//        if (businessProductListDTO.getForProcess()) {
//            transferDataList = jsonObject;
//            JSONArray productArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(saasUpdateHelp.getJsonObjectOrDefaultFromFormData(jsonObject, TransferEnum.PRODUCTS.getAttr(), new JSONObject()), StringConstant.PRODUCT_LIST, new JSONArray());
//            Map<Long, ProductEntityExt> productMap = getProductMap(new HashSet<>(), corpid, productArray);
//            getProductList(corpid, transferProducts, productBaseInfoList, jsonObject, productMap);
//        } else {
//            TransferEntityExt transferEntity = transferModel.getByKey(transferId, corpid);
//            transferDataList = transferEntity.getData();
//            // 获取调拨单关联产品
//            transferProducts = ( List<TransferProductEntity>) PageHelperUtil.getEntityList(modelMap, pageHelper, transferProductModel);
//        }
//        Long outWarehouseId = FastJsonHelper.getLongOrDefaultFromFormData(transferDataList, TransferEnum.OUT_WAREHOUSE_ID.getAttr(), 0L);
//        Long intoWarehouseId = FastJsonHelper.getLongOrDefaultFromFormData(transferDataList, TransferEnum.INTO_WAREHOUSE_ID.getAttr(), 0L);
//        Set<Long> productIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        productIds.add(-1L);
//        List<Long> transferProductIds = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        transferProductIds.add(-1L);
//        List<Long> warehouseIds = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        warehouseIds.add(-1L);
//        for (TransferProductEntity entity : transferProducts) {
//            productIds.add(entity.getProductId());
//            transferProductIds.add(entity.getId());
//            warehouseIds.add(entity.getIntoWarehouseId());
//            warehouseIds.add(entity.getOutWarehouseId());
//        }
//
//        // 根据productIdIn获取对应产品信息
//        Map<Long, PaasFormDataEntityExt> productMap = productService.getProductMapByIdIn(productIds, corpid, null);
//        for (TransferProductEntity entity : transferProducts) {
//            PaasFormDataEntityExt productEntityExt = productMap.get(entity.getProductId());
//            if (Objects.nonNull(productEntityExt)) {
//                String barcode = FastJsonHelper.getStringOrDefaultFromFormData(productEntityExt.getData(), ProductEnum.BARCODE.getAttr(), "");
//                entity.setBarcode(barcode);
//                entity.setImageUrlArray(saasUpdateHelp.getJsonArrFromFormData(productEntityExt.getData(),ProductEnum.PRODUCT_IMGS.getAttr()));
//            }
//        }
//        // 出入库选择调拨单时，要获取产品所在的仓库信息
//        Map<Long, JSONObject> transferProductWarehouseMap = null;
//        if (isInstock || isOutstock) {
//            transferProductWarehouseMap = warehouseModel.findWarehouseObjMapByIdIn(warehouseIds, corpid);
//        }
//        // 需要查询的字段
//        List<String> fieldList = Arrays.asList("productId", "num", "cost");
//        // 调拨产品在出库仓库的分仓库存
//        Map<Long, ProductWarehouseEntity> outWarehouseMap = productWarehouseModel.getWarehouseProductList(corpid, outWarehouseId, new ArrayList<>(productIds), fieldList);
//        // 调拨产品在入库仓库的分仓库存
//        Map<Long, ProductWarehouseEntity> intoWarehouseMap = productWarehouseModel.getWarehouseProductList(corpid, intoWarehouseId, new ArrayList<>(productIds), fieldList);
//        // 调拨单产品冗余信息
//        if (!businessProductListDTO.getForProcess()) {
//            productBaseInfoList = productBaseInfoModel.getProductBaseInfoList(corpid, XbbRefTypeEnum.TRANSFER_PRODUCT.getCode(), transferProductIds);
//        }
//        Map<Long, ProductBaseInfoEntity> baseInfoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        for (ProductBaseInfoEntity productBaseInfoEntity : productBaseInfoList) {
//            baseInfoMap.put(productBaseInfoEntity.getRefId(), productBaseInfoEntity);
//        }
//        // 用于存放当前启用的产品模板解释的map
//        Map<String, FieldAttrEntity> nowProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        Map<String, FieldAttrEntity> nowStockProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//        saasAddHelp.getRelativeProductExplainsFromDB(corpid, nowProductExplainMap, nowStockProductExplainMap);
//
//        // 返回给前端的接受对象
//        JSONObject productFinalObj = new JSONObject();
//        JSONArray productArray = new JSONArray();
//        Map<Integer, JSONObject> productSortMap = new TreeMap<>();
//        BusinessProductListVO businessProductListVO = new BusinessProductListVO();
//        // 与productList同级，返回对应关联产品的attr
//        String attrStr = "";
//
//        if (isInstock) {
//            // 调拨入库
//            attrStr = InstockEnum.PRODUCT.getAttr();
//
//            // 获取调拨单生成的出库单
//            PaasFormDataEsListVO outstockListFromEs = outstockService.getOutstockListFromEs(corpid, transferId, OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode());
//            List<PaasFormDataEntityExt> outstockPaasFormDataESList = outstockListFromEs.getPaasFormDataESList();
//            PaasFormDataEntityExt outstockPaasFormDataEsEntity = null;
//            if (outstockPaasFormDataESList != null && outstockPaasFormDataESList.size() > 0) {
//                outstockPaasFormDataEsEntity = outstockPaasFormDataESList.get(0);
//            }
//
//            Map<Long, OutstockProductEntity> outstockProductMap = new HashMap<>();
//            if (outstockPaasFormDataEsEntity != null) {
//                // 出库单id
//                Long outstockId = outstockPaasFormDataEsEntity.getDataId();
//                // 获取出库单关联的产品出库成本
//                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//                param.put(ParameterConstant.CORPID, corpid);
//                param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
//                param.put("outWarehouseId", outstockId);
//                List<OutstockProductEntity> outstockProductEntitys = outstockProductModel.findEntitys(param);
//                for (OutstockProductEntity outstockProductEntity : outstockProductEntitys) {
//                    outstockProductMap.put(outstockProductEntity.getProductId(), outstockProductEntity);
//                }
//            }
//
//            for (TransferProductEntity transferProduct : transferProducts) {
//                Long productId = transferProduct.getProductId();
//                if (!outstockProductMap.containsKey(productId)) {
//                    // 只有调拨出库了的产品才可以调拨入库
//                    continue;
//                }
//                OutstockProductEntity outstockProduct = outstockProductMap.get(productId);
//                Long transferProductId = transferProduct.getId();
//                InstockProductEntityExt instockProductExt = new InstockProductEntityExt();
//                instockProductExt.setParentId(transferProduct.getParentId());
//                instockProductExt.setProductId(productId);
//                instockProductExt.setProductName(transferProduct.getProductName());
//                instockProductExt.setProductNo(transferProduct.getProductNo());
//                // 格式化规格
//                String specification = specificationModel.joinSpecification(transferProduct.getProductSpecification());
//                instockProductExt.setProductSpecification(specification);
//                instockProductExt.setProductUnit(transferProduct.getProductUnit());
//                // 调拨入库的数量是调拨出库的数量
//                instockProductExt.setProductNum(outstockProduct.getProductNum());
//                instockProductExt.setWarehouseId(transferProduct.getIntoWarehouseId());
//                // 设置仓库信息
//                if (transferProduct.getIntoWarehouseId() != null) {
//                    JSONObject warehouseObj = transferProductWarehouseMap.get(transferProduct.getIntoWarehouseId());
//                    instockProductExt.setWarehouseObj(warehouseObj);
//                }
//                // 获取对应的产品信息
//                PaasFormDataEntityExt product = productMap.get(productId);
//
//                Double productStock = 0.0;
//                String batch = "";
//                if (product != null) {
//                    JSONObject productDataList = product.getData();
//                    instockProductExt.setBarcode(FastJsonHelper.getStringOrDefaultFromFormData(productDataList, ProductEnum.BARCODE.getAttr(), ""));
//                    // 产品的总库存
//                    productStock = productDataList.getDouble(ProductEnum.STOCK.getAttr());
//                    // 产品图片
//                    instockProductExt.setImageUrlArray(productDataList.getJSONArray(ProductEnum.PRODUCT_IMGS.getAttr()));
//                }
//
//                // 库存计算
//                ProductBaseInfoEntity productBaseInfo = baseInfoMap.get(transferProductId);
//                if (productBaseInfo == null) {
//                    ProductWarehouseEntity productWarehouse = intoWarehouseMap.get(productId);
//                    if (productWarehouse != null) {
//                        productStock = productWarehouse.getNum();
//                    }
//                } else {
//                    batch = productBaseInfo.getBatch();
//                    // 判断有没有批次信息
//                    if (StringUtil.isNotEmpty(batch)) {
//                        // 获取该批次产品在当前仓库下的库存
//                        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//                        params.put("corpid", corpid);
//                        params.put("del", 0);
//                        params.put("productId", productId);
//                        params.put("warehouseId", transferProduct.getIntoWarehouseId());
//                        params.put("batch", batch);
////                        List<ProductStockInfoEntity> productStockList = productStockInfoService.getValidBatchInfoList(corpid, params);
//                        BoolQueryBuilder boolQueryBuilder = boolQuery();
//                        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
//                        boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
//                        boolQueryBuilder.filter(termsQuery("productId", productIds));
//                        boolQueryBuilder.filter(termQuery("warehouseChecked",1));
//                        if (!Objects.isNull(transferProduct.getIntoWarehouseId())){
//                            boolQueryBuilder.filter(termQuery("warehouseId", transferProduct.getIntoWarehouseId()));
//                        }
//                        if (!Objects.isNull(batch)){
//                            boolQueryBuilder.filter(termQuery("batch.keyword",batch));
//                        }
//                        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//                        sourceBuilder.query(boolQueryBuilder);
//                        sourceBuilder.size(0);
//                        SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum("num").field("num");
//                        sourceBuilder.aggregation(sumAggregationBuilder);
//                        String index = IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO.getIndex();
//                        String type = IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO.getType();
//                        SearchRequest searchRequest = new SearchRequest(index).types(type);
//                        searchRequest.source(sourceBuilder);
//                        JSONObject aggJson = xbbElasticsearchRestTemplate.getAggResponseJson(searchRequest);
//                        Integer sumTotal = aggJson.getJSONObject("hits").getInteger("total");
//                        if(sumTotal !=null && sumTotal > 0) {
//                            JSONObject aggJsonObject = aggJson.getJSONObject("aggregations");
//                            if (aggJsonObject != null && !aggJsonObject.isEmpty()) {
//                                productStock = aggJsonObject.getJSONObject("num").getDouble("value");
//                            }
//                        }
//                        /*List<ProductStockEntity> productStockEntityList = productStockModel.getValidBatchInfoList(new ArrayList<>(productIds),corpid,transferProduct.getIntoWarehouseId(),batch, fieldList);
//                        // 批次总库存
//                        Double totalBatchStock = 0D;
//                        for (ProductStockEntity stockInfo : productStockEntityList) {
//                            if (stockInfo.getNum() != null) {
//                                totalBatchStock = Arith.add(totalBatchStock, stockInfo.getNum());
//                            }
//                        }
//                        productStock = totalBatchStock;*/
//                    } else {
//                        ProductWarehouseEntity productWarehouse = intoWarehouseMap.get(productId);
//                        if (productWarehouse != null) {
//                            productStock = productWarehouse.getNum();
//                        }
//                    }
//                    instockProductExt.setGuaranteePeriod(productBaseInfo.getGuaranteePeriod());
//                    instockProductExt.setProduceDate(productBaseInfo.getProduceDate());
//                    instockProductExt.setBatch(batch);
//                    instockProductExt.setMemo(productBaseInfo.getMemo());
//                }
//                instockProductExt.setStock(productStock);
//                OutstockProductEntity outstockProductEntity = outstockProductMap.get(productId);
//                if (Objects.nonNull(outstockProductEntity)) {
//                    // 调拨出库产品成本价作为调拨入库产品成本价
//                    instockProductExt.setCost(outstockProductEntity.getCost());
//                } else {
//                    instockProductExt.setCost(0D);
//                }
//
//                // 构建格式化入库产品的DTO
//                FormatInstockProductDTO formatInstockProductDTO = new FormatInstockProductDTO();
//                BeanUtil.copyProperties(businessProductListDTO, formatInstockProductDTO);
//                formatInstockProductDTO.setUserEntity(userEntity);
//                if (productBaseInfo != null) {
//                    ProductStockInfoEntity productStockInfoEntity = new ProductStockInfoEntity();
//                    BeanUtil.copyProperties(productBaseInfo, productStockInfoEntity);
//                    instockProductExt.setProductStockInfoEntity(productStockInfoEntity);
//                }
//                formatInstockProductDTO.setInstockProductExt(instockProductExt);
//                formatInstockProductDTO.setNowProductExplainMap(nowProductExplainMap);
//                formatInstockProductDTO.setNowStockProductExplainMap(nowStockProductExplainMap);
//                JSONObject productObj = instockService.getFormatProductJsonArray(formatInstockProductDTO);
//                productSortMap.put(transferProduct.getSort(), productObj);
//            }
//        }
//        if (isOutstock) {
//            attrStr = OutstockEnum.PRODUCT.getAttr();
//            // 出库调拨单
//            for (TransferProductEntity transferProduct : transferProducts) {
//                Long transferProductId = transferProduct.getId();
//                String productName = transferProduct.getProductName();
//                Long productId = transferProduct.getProductId();
//                OutstockProductEntityExt outstockProductExt = new OutstockProductEntityExt();
//                outstockProductExt.setParentId(outstockProductExt.getProductId());
//                outstockProductExt.setProductId(productId);
//                outstockProductExt.setProductName(productName);
//                outstockProductExt.setProductNo(transferProduct.getProductNo());
//                String specification = transferProduct.getProductSpecification();
//                outstockProductExt.setProductSpecification(specificationModel.joinSpecification(specification));
//                outstockProductExt.setProductUnit(transferProduct.getProductUnit());
//                outstockProductExt.setProductNum(transferProduct.getProductNum());
//                outstockProductExt.setWarehouseId(transferProduct.getOutWarehouseId());
//                // 设置仓库信息
//                if (transferProduct.getOutWarehouseId() != null) {
//                    JSONObject warehouseObj = transferProductWarehouseMap.get(transferProduct.getOutWarehouseId());
//                    outstockProductExt.setWarehouseObj(warehouseObj);
//                }
//
//                Double productStock = 0.0;
//                String batch = "";
//                Double productCost = 0D;
//
//                PaasFormDataEntityExt product = productMap.get(productId);
//                if (product != null) {
//                    JSONObject productDataList = product.getData();
//                    outstockProductExt.setBarcode(productDataList.getString(ProductEnum.BARCODE.getAttr()));
//                    // 产品的总库存
//                    productStock = productDataList.getDouble(ProductEnum.STOCK.getAttr());
//                    productCost = saasUpdateHelp.getDoubleOrDefaultFromFormData(productDataList, ProductEnum.COST.getAttr(), 0D);
//                    // 产品图片
//                    outstockProductExt.setImageUrlArray(productDataList.getJSONArray(ProductEnum.PRODUCT_IMGS.getAttr()));
//                }
//                ProductBaseInfoEntity productBaseInfo = baseInfoMap.get(transferProductId);
//                if (productBaseInfo == null) {
//                    ProductWarehouseEntity productWarehouse = outWarehouseMap.get(productId);
//                    // 选择了仓库
//                    if (productWarehouse != null) {
//                        // 产品的仓库库存
//                        productStock = productWarehouse.getNum();
//                        // 产品仓库成本
//                        productCost = productWarehouse.getCost();
//                    }
//                } else {
//                    batch = productBaseInfo.getBatch();
//                    // 选择了批次
//                    if (StringUtil.isNotEmpty(batch)) {
//                        // 获取该批次产品在当前仓库下的库存
//                        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
//                        params.put("corpid", corpid);
//                        params.put("del", 0);
//                        params.put("productId", productId);
//                        params.put("warehouseId", transferProduct.getOutWarehouseId());
//                        params.put("batch", batch);
////                        List<ProductStockInfoEntity> productStockList = productStockInfoService.getValidBatchInfoList(corpid, params);
//                        // 需要查询的字段
//                        List<String> fields = Arrays.asList("num", "cost");
//                        List<ProductStockEntity> productStockEntityList = productStockModel.getValidBatchInfoList(new ArrayList<>(productIds),corpid,transferProduct.getOutWarehouseId(),batch, fields);
//                        // 批次总成本
//                        Double totalBatchCost = 0D;
//                        // 批次总库存
//                        Double totalBatchStock = 0D;
//                        for (ProductStockEntity stockInfo : productStockEntityList) {
//                            if (stockInfo.getNum() != null && stockInfo.getCost() != null) {
//                                totalBatchCost = Arith.add(totalBatchCost, Arith.mul(stockInfo.getCost(), stockInfo.getNum()));
//                                totalBatchStock = Arith.add(totalBatchStock, stockInfo.getNum());
//                            }
//                        }
//                        if (totalBatchStock != 0D) {
//                            // 批次平均成本
//                            productCost = Arith.div(totalBatchCost, totalBatchStock);
//                        }
//                        productStock = totalBatchStock;
//                    } else {
//                        ProductWarehouseEntity productWarehouse = outWarehouseMap.get(productId);
//                        if (productWarehouse != null) {
//                            // 产品的仓库库存
//                            productStock = productWarehouse.getNum();
//                            // 产品仓库成本
//                            productCost = productWarehouse.getCost();
//                        }
//                    }
//                    outstockProductExt.setGuaranteePeriod(productBaseInfo.getGuaranteePeriod());
//                    outstockProductExt.setProduceDate(productBaseInfo.getProduceDate());
//                    outstockProductExt.setBatch(batch);
//                    outstockProductExt.setMemo(productBaseInfo.getMemo());
//                }
//                outstockProductExt.setCost(productCost);
//                outstockProductExt.setStock(productStock);
//
//                // 构建格式化出库产品的DTO
//                FormatOutstockProductDTO formatOutstockProductDTO = new FormatOutstockProductDTO();
//                BeanUtil.copyProperties(businessProductListDTO, formatOutstockProductDTO);
//                formatOutstockProductDTO.setCorpid(corpid);
//                formatOutstockProductDTO.setUserEntity(userEntity);
//                if (productBaseInfo != null) {
//                    ProductStockInfoEntity productStockInfoEntity = new ProductStockInfoEntity();
//                    BeanUtil.copyProperties(productBaseInfo, productStockInfoEntity);
//                    outstockProductExt.setProductStockInfoEntity(productStockInfoEntity);
//                }
//                formatOutstockProductDTO.setOutstockProductExt(outstockProductExt);
//                formatOutstockProductDTO.setNowProductExplainMap(nowProductExplainMap);
//                formatOutstockProductDTO.setNowStockProductExplainMap(nowStockProductExplainMap);
//
//                JSONObject productObj = outstockService.getFormatProductJsonArray(formatOutstockProductDTO);
//                productSortMap.put(transferProduct.getSort(), productObj);
//            }
//        }
//        if (generalGetProduct) {
//            attrStr = TransferEnum.PRODUCTS.getAttr();
//            // 正常获取调拨单产品
//            for (TransferProductEntity transferProduct : transferProducts) {
//                Long productId = transferProduct.getProductId();
//                Long transferProductId = transferProduct.getId();
//                TransferProductEntityExt transferProductEntityExt = new TransferProductEntityExt();
//                BeanUtil.copyProperties(transferProduct, transferProductEntityExt);
//                ProductBaseInfoEntity productBaseInfo = baseInfoMap.get(transferProductId);
//                Double productStock = getProductStock(productBaseInfo, outWarehouseMap, outWarehouseId, corpid, productId);
//                // 数量小数精度
//                productStock = attrDecimalPrecisionHelper.setPrecision(productStock, nowProductExplainMap, ProductEnum.STOCK.getAttr());
//
//                transferProductEntityExt.setStock(productStock);
//                // 构建格式化调拨产品的DTO
//                FormatTransferProductDTO formatTransferProductDTO = new FormatTransferProductDTO();
//                formatTransferProductDTO.setCorpid(corpid);
//                transferProductEntityExt.setProductBaseInfoEntity(productBaseInfo);
//                formatTransferProductDTO.setTransferProductEntityExt(transferProductEntityExt);
//                formatTransferProductDTO.setNowProductExplainMap(nowProductExplainMap);
//                formatTransferProductDTO.setNowStockProductExplainMap(nowStockProductExplainMap);
//                JSONObject productObj = getFormatProductJsonArray(formatTransferProductDTO);
//                productSortMap.put(transferProductEntityExt.getSort(), productObj);
//            }
//        }
//        // 产品排序
//        productArray.addAll(productSortMap.values());
//        productFinalObj.put(StringConstant.PRODUCT_LIST, productArray);
//        productFinalObj.put(StringConstant.REDUNDANT_FIELD_ATTR_BEGIN_FLAG, attrStr);
//        if (generalGetProduct && detailGet) {
//            // 普通获取产品并且是详情时，增加表头解释
//            productFinalObj.put(BusinessConstant.EXPLAINS, saasUpdateHelp.getSelectProductExplains(XbbRefTypeEnum.TRANSFER, corpid, TransferEnum.PRODUCTS.getAttr()));
//        }
//        businessProductListVO.setPageHelper(pageHelper);
//        businessProductListVO.setProduct(productFinalObj);
//        return businessProductListVO;
//    }

    @Override
    public void batchEditAttr(TransferEditAttrUpdateDTO transferEditAttrUpdateDTO) throws XbbException {
        try {
            List<TransferUpdateDTO> transferList = new ArrayList<>();
            transferEditAttrUpdateDTO.getDataIdList().forEach((item)->{
                TransferUpdateDTO transferUpdateDTO = new TransferUpdateDTO();
                transferUpdateDTO.setId(item);
                JSONObject data = ProSaveHelp.getBatchUpdateData(transferEditAttrUpdateDTO.getFieldEditedList());
                transferUpdateDTO.setData(data);
                transferList.add(transferUpdateDTO);
            });
            List<TransferEntityExt> transferEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (!transferList.isEmpty()) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("corpid", transferEditAttrUpdateDTO.getCorpid());
                param.put("idIn", transferEditAttrUpdateDTO.getDataIdList());
                transferEntityList = transferModel.findEntitys(param);
                if (Objects.isNull(transferEntityList)){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }

                TransferUpdateBatchDTO transferUpdateBatchDTO = new TransferUpdateBatchDTO();
                BeanUtil.copyProperties(transferEditAttrUpdateDTO, transferUpdateBatchDTO);
                transferUpdateBatchDTO.setTransferList(transferList);
                updateBatch(transferUpdateBatchDTO);
            }

            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> dataIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (TransferEntityExt item : transferEntityList) {
                dataIdList.add(item.getId());
                String serialNo = item.getSerialNo();
                updataItemList.add(serialNo);
            }
            String updataItem = StringUtils.join(updataItemList, "，");
            String userId = transferEditAttrUpdateDTO.getUserId();
            String corpid = transferEditAttrUpdateDTO.getCorpid();
            String loginUserName = transferEditAttrUpdateDTO.getLoginUserName();
            Boolean isFieldDependence = transferEditAttrUpdateDTO.getIsFieldDependence();
            // 标签特殊处理
            Integer fieldType = transferEditAttrUpdateDTO.getFieldType();
            logHelp.analysisLabel(corpid, fieldType, isFieldDependence, transferEditAttrUpdateDTO.getLogFieldEditedList());

            String changedLogItemsStr = logHandleHelp.getChangedLogItemsStr(transferEditAttrUpdateDTO.getLogFieldEditedList());
            if(dataIdList.size() > 1 ){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, XbbRefTypeEnum.TRANSFER.getName(),
                        changedLogItemsStr, dataIdList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(XbbRefTypeEnum.TRANSFER.getName());
                infoArrPojo.setContent(updataItem);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.TRANSFER, OperateTypeEnum.EDIT,
                        "", "", memo, transferEditAttrUpdateDTO.getHttpHeader());
            } else if (Objects.equals(dataIdList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_ATTR), loginUserName, XbbRefTypeEnum.TRANSFER.getName(), updataItem,
                        changedLogItemsStr);
                mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.TRANSFER, OperateTypeEnum.EDIT,
                        dataIdList.get(0).toString(), updataItem, memo, transferEditAttrUpdateDTO.getHttpHeader());
            }
        } catch (XbbException e){
            throw e;
        } catch (Exception e) {
            LOG.error("transferService.batchEditAttr 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void updateBatch(TransferUpdateBatchDTO transferUpdateBatchDTO) throws XbbException {
        try {
            List<UpdateDataEntity> transferList = new ArrayList<>();
            String corpid = transferUpdateBatchDTO.getCorpid();
            transferUpdateBatchDTO.getTransferList().forEach((item)->{
                UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid);
                transferList.add(updateDataEntity);
            });
            if (!transferList.isEmpty()) {
                transferModel.updateBatch(transferList, corpid);
            }
        } catch (Exception e) {
            LOG.error("transferService.updateBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        String corpid = importFormDataDTO.getCorpid();
        // data 数据
        JSONObject dataJson = new JSONObject();

        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);

        // 遍历数据
        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            String attr = fieldAttrEntityForImport.getAttr();
            Integer fieldType = fieldAttrEntityForImport.getFieldType();
            String attrName = fieldAttrEntityForImport.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);

            if (Objects.equals(attr, TransferEnum.PRODUCTS.getAttr())) {
                importHelper.formatCommonProduct(titlePojoList, dataJson, rowValueList, fieldAttrEntityForImport, XbbRefTypeEnum.TRANSFER.getCode(), corpid);
            } else if (Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType())) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, fieldAttrEntityForImport, dataJson);
            } else if (Objects.equals(attr, TransferEnum.MANAGER_NAME.getAttr())) {
                importHelper.formatOwnId4Import(formDataAddDTO, fieldAttrEntityForImport, cellValue);
            } else if (Objects.equals(attr, TransferEnum.OUT_WAREHOUSE_ID.getAttr()) || Objects.equals(attr, TransferEnum.INTO_WAREHOUSE_ID.getAttr())) {
                importHelper.formatWareHouse4Import(dataJson, fieldAttrEntityForImport, attr, cellValue);
            } else if (Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType())) {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200022);
                }
                formDataAddDTO.setSerialNo(cellValue.toString());
            } else {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(fieldAttrEntityForImport.getFieldType())) {
                    importHelper.formatCommonField(dataJson, fieldAttrEntityForImport, cellValue);
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())) {
                    importHelper.formatLinkData(cellValue, fieldAttrEntityForImport, dataJson);
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                    importHelper.formatLinkDataMulti(cellValue, importFormDataDTO, fieldAttrEntityForImport, dataJson);
                } else {
                    dataJson.put(attr, cellValue);
                }
            }
        }
        // 加入当前库存数量
        JSONArray productJsonArray = dataJson.getJSONArray(TransferEnum.PRODUCTS.getAttr());
        JSONArray wareHouseArray = dataJson.getJSONArray(TransferEnum.OUT_WAREHOUSE_ID.getAttr());
        if (wareHouseArray == null || wareHouseArray.isEmpty()) {
            throw new XbbException(WarehouseErrorCodeEnum.API_ERROR_244016.getCode(), WarehouseErrorCodeEnum.API_ERROR_244016.getMsg());
        }
        Long wareHouseId = wareHouseArray.getJSONObject(0).getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
        List<Long> productIdList = new ArrayList<>();
        List<String> batchKeyList = new ArrayList<>();
        for (int i = 0; i < productJsonArray.size(); i++) {
            JSONObject productObj = productJsonArray.getJSONObject(i);
            Long productId = productObj.getJSONObject(SelectProductEnum.PRODUCT.getAttr()).getLong(StringConstant.DATA_ID);
            productIdList.add(productId);
            String batch = productObj.getString(SelectProductEnum.BATCH.getAttr());
            Long produceDate = productObj.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()) == null ? 0L : productObj.getLong(SelectProductEnum.PRODUCE_DATE.getAttr());
            Long guaranteePeriod = productObj.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()) == null ? 0L : productObj.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr());
            StringBuilder sb;
            if (StringUtil.isNotEmpty(batch)) {
                sb = new StringBuilder();
                sb.append(productId).append(StringConstant.CROSS).append(wareHouseId).append(StringConstant.CROSS).append(batch).append(StringConstant.CROSS).append(produceDate).append(StringConstant.CROSS).append(guaranteePeriod * TimeConstant.SECONDS_PER_DAY);
                batchKeyList.add(sb.toString());
            }
        }
        // 需要查询的字段
        List<String> fieldList = Arrays.asList(ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("productId"), ProductWarehouseSubFormEnum.getAttrConnectDataByDbAttr("num"));
        Map<Long, ProductWarehouseEntity> productWarehouseMap = productWarehouseModel.getWarehouseProductList(importFormDataDTO.getCorpid(), wareHouseId, productIdList, fieldList);

        Map<String, ProductStockEntity> productBatchWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (!batchKeyList.isEmpty()) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put(ParameterConstant.CORPID, corpid);
            params.put("batchKeyIn", batchKeyList);
            params.put("warehouseChecked", 1);
            List<ProductStockEntity> productStockEntities = productStockModel.findEntitys(params);
            productStockEntities.forEach(item -> {
                String key = item.getBatchKey();
                productBatchWarehouseMap.put(key, item);
            });
        }
        JSONArray tempJsonArray = new JSONArray();
        StringBuilder sb;
        for (int i = 0; i < productJsonArray.size(); i++) {
            JSONObject productObj = productJsonArray.getJSONObject(i);
            Long productId = productObj.getJSONObject(SelectProductEnum.PRODUCT.getAttr()).getLong(StringConstant.DATA_ID);
            String batch = productObj.getString(SelectProductEnum.BATCH.getAttr());
            Long produceDate = productObj.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()) == null ? 0L : productObj.getLong(SelectProductEnum.PRODUCE_DATE.getAttr());
            Long guaranteePeriod = productObj.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()) == null ? 0L : productObj.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr());
            if (StringUtil.isNotEmpty(batch)) {
                sb = new StringBuilder();
                sb.append(productId).append(StringConstant.CROSS).append(wareHouseId).append(StringConstant.CROSS).append(batch).append(StringConstant.CROSS).append(produceDate).append(StringConstant.CROSS).append(guaranteePeriod * TimeConstant.SECONDS_PER_DAY);
                ProductStockEntity productStockEntity = productBatchWarehouseMap.get(sb.toString());
                if (productStockEntity != null) {
                    productObj.put(SelectProductEnum.STOCK.getAttr(), productStockEntity.getNum());
                    if (Objects.nonNull(productStockEntity.getGuaranteePeriod())) {
                        productObj.put(SelectProductEnum.GUARANTEE_PERIOD.getAttr(), Arith.div(productStockEntity.getGuaranteePeriod(), 86400));
                    }
                    productObj.put(SelectProductEnum.PRODUCE_DATE.getAttr(), productStockEntity.getProduceDate());
                } else {
                    throw new XbbException(ImportErrorCodeEnum.API_ERROR_235032.getCode(), ImportErrorCodeEnum.API_ERROR_235032.getMsg());
                }
            } else {
                ProductWarehouseEntity productWarehouse = productWarehouseMap.get(productId);
                if (productWarehouse != null) {
                    productObj.put(SelectProductEnum.STOCK.getAttr(), productWarehouse.getNum());
                }
            }
            tempJsonArray.add(productObj);
        }
        dataJson.put(TransferEnum.PRODUCTS.getAttr(), tempJsonArray);
        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }

    @Override
    public void formatExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        // 所有产品
        List<Long> idList = new ArrayList<>();
        paasFormDataESList.forEach(item -> idList.add(item.getDataId()));
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.CORPID, formDataListDTO.getCorpid());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put("transferIdIn", idList);
        List<ProductEntityExt> productList = productModel.findEntitys(params);
        Map<Long, ProductEntityExt> productMap = new HashMap<>();
        productList.forEach(item -> productMap.put(item.getId(), item));
        // 调拨关联产品map
        params.put("orderByStr","sort");
        List<TransferProductEntity> transferProductList = transferProductModel.findEntitys(params);
        Map<Long, List<TransferProductEntity>> transferProductMap = new HashMap<>();
        transferProductList.forEach(item -> {
            Long refId = item.getTransferId();
            if (transferProductMap.containsKey(refId)) {
                transferProductMap.get(refId).add(item);
            } else {
                List<TransferProductEntity> productEntityList = new ArrayList<>();
                productEntityList.add(item);
                transferProductMap.put(refId, productEntityList);
            }
        });

        // 库存信息map
        params.remove("transferIdIn");
        params.remove("orderByStr");
        params.put("refType", XbbRefTypeEnum.TRANSFER_PRODUCT.getCode());
        List<ProductBaseInfoEntity> stockInfoList = productBaseInfoModel.findEntitys(params);
        Map<Long, ProductBaseInfoEntity> stockInfoMap = new HashMap<>();
        stockInfoList.forEach(item -> stockInfoMap.put(item.getRefId(), item));

        // 产品，库存产品
        FieldAttrEntityForImport productFieldAttr = new FieldAttrEntityForImport();
        for (FieldAttrEntityForImport item : fieldAttrList) {
            if (Objects.equals(item.getAttr(), TransferEnum.PRODUCTS.getAttr())) {
                productFieldAttr = item;
            }
        }
        Map<String, MultiUnitItemPoJo> groupBaseUnitStringMap = relativeProductHelp.getGroupBaseUnitStringMap(formDataListDTO.getCorpid());

        // 暂时只处理产品
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
            JSONObject formDataObj = paasFormDataEntityExt.getData();
            String productAttr = productFieldAttr.getAttr();
            Long dataId = paasFormDataEntityExt.getDataId();
            List<TransferProductEntity> transferProductEntityList = transferProductMap.get(dataId);
            if (transferProductEntityList == null || transferProductEntityList.size() == 0) {
                formDataObj.put(productAttr, new JSONArray());
                continue;
            }
            JSONArray productArray = new JSONArray();
            for (TransferProductEntity transferProductEntity : transferProductEntityList) {
                Long productId = transferProductEntity.getProductId();
                Double num = transferProductEntity.getProductNum();
                double rate = transferProductEntity.getRate() == null ? 1:transferProductEntity.getRate();
                // 产品信息转换
                JSONObject productObj = transferProductEntity.getData() == null ? new JSONObject() : transferProductEntity.getData();
                importHelper.formatProduct4Export(productMap, null, productId, num, null, productObj);
                productObj.put(TransferProductEnum.OUTSTOCK_NUM.getAttr(), Arith.div(transferProductEntity.getOutstockNum(), rate));
                productObj.put(TransferProductEnum.INSTOCK_NUM.getAttr(), Arith.div(transferProductEntity.getInstockNum(), rate));
                productObj.put(TransferProductEnum.WAIT_INSTOCK_NUM.getAttr(), Arith.div(Arith.sub(transferProductEntity.getOutstockNum(),transferProductEntity.getInstockNum()), rate));
                importHelper.formatBatch4Export(productObj);
                //基本单位时直接塞入productUnit
                if (Objects.isNull(transferProductEntity.getBusinessUnit())){
                    if (Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                        productObj.put(ProductEnum.UNIT.getAttr(), groupBaseUnitStringMap.getOrDefault(productObj.getString(ProductEnum.UNIT.getAttr()), new MultiUnitItemPoJo()).getBaseValue());
                        transferProductEntity.setProductUnit(productObj.getString(ProductEnum.UNIT.getAttr()));
                    }
                    productObj.put(SelectProductEnum.NUM.getAttr(), transferProductEntity.getProductNum());
                }else {
                    productObj.put(ProductEnum.UNIT.getAttr(), transferProductEntity.getBusinessUnit());
                    productObj.put(SelectProductEnum.NUM.getAttr(), transferProductEntity.getBusinessNum());
                }

                if(Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), transferProductEntity.getProductUnit());
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(),  transferProductEntity.getProductNum());
                }else {
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), "");
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(), "");
                }
                productArray.add(productObj);
               /* // 库存产品信息转换
                ProductBaseInfoEntity baseInfoEntity = stockInfoMap.get(transferProductEntity.getId());
                importHelper.formatBaseInfo4Export(productObj, baseInfoEntity);*/
            }
            formDataObj.put(productAttr, productArray);
        }
    }

    /**
     * 获取产品返回对象
     *
     * @param formatTransferProductDTO
     * @return 对象
     * @throws XbbException 异常
     */
    private JSONObject getFormatProductJsonArray(FormatTransferProductDTO formatTransferProductDTO) throws XbbException {
        TransferProductEntityExt transferProductEntityExt = formatTransferProductDTO.getTransferProductEntityExt();
        Map<String, FieldAttrEntity> nowProductExplainMap = formatTransferProductDTO.getNowProductExplainMap();
        ProductBaseInfoEntity productBaseInfo = transferProductEntityExt.getProductBaseInfoEntity();
        if (productBaseInfo == null) {
            productBaseInfo = new ProductBaseInfoEntity();
        }
        JSONArray attrArray = new JSONArray();
        JSONObject productObj = new JSONObject();
        // 获取关联产品需要展示的字段
        BusinessProductEnum businessProductEnum = BusinessProductEnum.getByCode(XbbRefTypeEnum.TRANSFER.getCode());
        List<RelativeProductEnum> businessProductEnumList = businessProductEnum.getList();
        for (RelativeProductEnum productEnum : businessProductEnumList) {
            String saasAttr = productEnum.getSaasAttr();
            FieldAttrEntity fieldAttrEntity = null;
            if (nowProductExplainMap.containsKey(saasAttr)) {
                fieldAttrEntity = nowProductExplainMap.get(saasAttr);
            }
            switch (productEnum) {
                case NAME:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(NAME, transferProductEntityExt.getProductName(), fieldAttrEntity));
                    break;
                case PRODUCT_NO:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(PRODUCT_NO, transferProductEntityExt.getProductNo(), fieldAttrEntity));
                    break;
                case BARCODE:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(BARCODE, transferProductEntityExt.getBarcode(), fieldAttrEntity));
                    break;
                case NUM:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(NUM, transferProductEntityExt.getProductNum(), fieldAttrEntity));
                    break;
                case STOCK:
                    JSONObject stockObj = saasUpdateHelp.formatSelectProduct4Show(STOCK, transferProductEntityExt.getStock(), fieldAttrEntity);
                    if (stockObj != null && !stockObj.isEmpty()) {
                        attrArray.add(stockObj);
                    }
                    break;
                case UNIT:
                    // 单位回显 存的key是0,1,2 回显对应的单位
                    String productUnit = transferProductEntityExt.getProductUnit();
                    String unitStr = productModel.getProductUnitTextByValue(productUnit, fieldAttrEntity);
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(UNIT, unitStr, fieldAttrEntity));
                    break;
                case SPECIFICATION:
                    // 格式化规格
                    String specification = specificationModel.joinSpecification(transferProductEntityExt.getProductSpecification());
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(SPECIFICATION, specification, fieldAttrEntity));
                    break;
                case BATCH:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(BATCH, productBaseInfo.getBatch(), fieldAttrEntity));
                    break;
                case GUARANTEE_PERIOD:
                    Double period = productBaseInfo.getGuaranteePeriod() == null ? 0D : productBaseInfo.getGuaranteePeriod() / (double) 86400;
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(GUARANTEE_PERIOD, period, fieldAttrEntity));
                    break;
                case PRODUCE_DATE:
                    Long productDate = productBaseInfo.getProduceDate();
                    String date = productDate == null ? "" : DateTimeUtil.getStringEpochSecond(productDate, DateTimeUtil.SDFDate);
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(PRODUCE_DATE, date, fieldAttrEntity));
                    break;
                case MEMO:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(MEMO, Objects.toString(productBaseInfo.getMemo(), ""), fieldAttrEntity));
                    break;
                case THUMBNAIL:
                    JSONArray defaultImage = new JSONArray(Collections.singletonList(StringConstant.DEFAULT_IMAGES));
                    JSONArray imageUrlArray = transferProductEntityExt.getImageUrlArray();
                    JSONArray imageList = imageUrlArray == null || imageUrlArray.isEmpty() ? defaultImage : imageUrlArray;
                    productObj.put(ProductEnum.THUMBNAIL.getSaasAttr(), imageList);
                    break;
                default:
                    break;
            }
        }
        productObj.put("result", attrArray);
        productObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, transferProductEntityExt.getProductId());
        productObj.put(StringConstant.BUSINESS_PRODUCT_ID, transferProductEntityExt.getId());
        productObj.put("parentId", transferProductEntityExt.getParentId());
        // TODO 库存产品自定义字段的回显
        return productObj;
    }

//    /**
//     * 格式化盘点单产品，显示给前端
//     *
//     * @param dataList            bom单实体数据
//     * @param saasAnalysisDataDTO 数据解析DTO
//     * @author feng.zheng
//     * @date 2019-02-01 15:19
//     */
//    @Override
//    public void formatProduct4Show(JSONObject dataList, SaasAnalysisDataDTO saasAnalysisDataDTO) throws XbbException {
//        if (dataList == null || saasAnalysisDataDTO == null) {
//            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
//        }
//        // 调拨单关联产品
//        BusinessProductListDTO businessProductListDTO = new BusinessProductListDTO();
//        BeanUtil.copyProperties(saasAnalysisDataDTO, businessProductListDTO);
//        BusinessProductListVO businessProductListVO;
//        if (businessProductListDTO.getForProcess()) {
//            businessProductListVO = getTransferProductList(businessProductListDTO, dataList);
//        } else {
//            businessProductListVO = getTransferProductList(businessProductListDTO, null);
//        }
//        JSONObject productFinalObj = businessProductListVO.getProduct();
//        dataList.put(TransferEnum.PRODUCTS.getAttr(), productFinalObj);
//    }

    @Override
    public PagingProductVO getPagingProduct(PagingProductDTO pagingProductDTO) throws XbbException {
        PagingProductVO pagingProductVO = new PagingProductVO();
        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, pagingProductDTO.getCorpid());
        modelMap.put(ParameterConstant.TRANSFER_ID, pagingProductDTO.getDataId());
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        modelMap.put(ParameterConstant.PAGE,  pagingProductDTO.getPage());
        modelMap.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
        PageHelper pageHelper = PageHelperUtil.getPageHelper(modelMap, transferProductModel, pagingProductDTO.getPageSize());
        List<TransferProductEntity> transferProductEntityList = (List<TransferProductEntity>) PageHelperUtil.getEntityList(modelMap, pageHelper, transferProductModel);
        if (pagingProductDTO.getUpdateDataTypeEnum().isDetail()) {
            DetailProductVO detailProductVO = formatProduct4DetailShow(transferProductEntityList, pagingProductDTO);
            pagingProductVO.setProductDataArr(detailProductVO.getProductDataArr());
        }
        pagingProductVO.setPageHelper(pageHelper);
        return pagingProductVO;
    }

    public DetailProductVO formatProduct4DetailShow(List<TransferProductEntity> transferProductEntityList, PagingProductDTO pagingProductDTO) throws XbbException{
        DetailProductVO detailProductVO = new DetailProductVO();
        Set<Long> productIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<Long> transferProductIdSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> outWarehouseIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<String> batchIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Set<String> warehouseKeySet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (TransferProductEntity transferProductEntity : transferProductEntityList) {
            productIds.add(transferProductEntity.getProductId());
            transferProductIdSet.add(transferProductEntity.getId());
            outWarehouseIdList.add(transferProductEntity.getOutWarehouseId());
            warehouseKeySet.add(transferProductEntity.getProductId() + "_" + transferProductEntity.getOutWarehouseId());

        }
        String corpid = pagingProductDTO.getCorpid();
        JSONArray productArray = new JSONArray();
        Map<Long, PaasFormDataEntityExt> productMap = productService.getProductMapByIdIn(productIds, corpid, DelEnum.NORMAL);
        List<ProductBaseInfoEntity> productBaseInfoList = productBaseInfoModel.getProductBaseInfoList(corpid, XbbRefTypeEnum.TRANSFER_PRODUCT.getCode(), transferProductIdSet);
        Map<Long, ProductBaseInfoEntity> baseInfoMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (ProductBaseInfoEntity productBaseInfoEntity : productBaseInfoList) {
            baseInfoMap.put(productBaseInfoEntity.getRefId(), productBaseInfoEntity);
            if (StringUtil.isNotEmpty(productBaseInfoEntity.getBatch())) {
                batchIdList.add(productBaseInfoEntity.getBatch());
            }
        }
        Map<String, Double> productWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (!productIds.isEmpty() && !outWarehouseIdList.isEmpty()) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put(ParameterConstant.CORPID, corpid);
//            params.put("productIdIn", productIds);
//            params.put("warehouseIdIn", outWarehouseIdList);
            params.put("warehouseKeyIn",warehouseKeySet);
            List<ProductWarehouseEntity> productWarehouseEntities = productWarehouseModel.findEntitysWithWarehouseChecked(params,null);
            productWarehouseEntities.forEach(item -> {
                String key = item.getProductId() + "_" + item.getWarehouseId();
                productWarehouseMap.put(key, item.getNum());
            });
        }
        if (!productIds.isEmpty() && !outWarehouseIdList.isEmpty() && !batchIdList.isEmpty()) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put(ParameterConstant.CORPID, corpid);
            params.put("productIdIn", productIds);
            params.put("warehouseIdIn", outWarehouseIdList);
            params.put("batchIn", batchIdList);
            List<ProductStockEntity> productStockEntities = productStockModel.findEntitys(params);
            productStockEntities.forEach(item -> {
                productWarehouseMap.put(item.getBatchKey(), item.getNum());
            });
        }
        PaasFormExplainEntity productExplains = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
        if (Objects.isNull(productExplains)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        Map<String, FieldAttrEntity> productExplainMap = ExplainUtil.getExplainMap(productExplains.getExplains(), null);
        for (TransferProductEntity transferProductEntity : transferProductEntityList) {
            Double stock;
            JSONObject json = new JSONObject();
            PaasFormDataEntityExt paasFormDataEntityExt = productMap.get(transferProductEntity.getProductId());
            ProductBaseInfoEntity productBaseInfoEntity = baseInfoMap.getOrDefault(transferProductEntity.getId(), new ProductBaseInfoEntity());
            if (StringUtil.isNotEmpty(productBaseInfoEntity.getBatch())) {
                stock = productWarehouseMap.getOrDefault(formDataValidateProductHelp.getBatchKey(transferProductEntity.getProductId(), transferProductEntity.getOutWarehouseId(), productBaseInfoEntity.getBatch(), productBaseInfoEntity.getProduceDate(), productBaseInfoEntity.getGuaranteePeriod()), 0D);
            } else {
                stock = productWarehouseMap.getOrDefault(transferProductEntity.getProductId() + "_" + transferProductEntity.getOutWarehouseId(), 0D);
            }
            if (Objects.nonNull(transferProductEntity.getData())) {
                json = transferProductEntity.getData();
            }
            if (Objects.nonNull(transferProductEntity.getBusinessUnit())) {
                transferProductEntity.setProductNum(Arith.div(transferProductEntity.getProductNum(), transferProductEntity.getRate()));
                transferProductEntity.setOutstockNum(Arith.div(transferProductEntity.getOutstockNum(), transferProductEntity.getRate()));
                transferProductEntity.setInstockNum(Arith.div(transferProductEntity.getInstockNum(), transferProductEntity.getRate()));
                transferProductEntity.setProductUnit(transferProductEntity.getBusinessUnit().toString());
            }
            for (TransferProductEnum transferProductEnum : TransferProductEnum.values()) {
                if (!UpdateDataTypeEnum.DETAIL.formatShow(transferProductEnum.getShowType())) {
                    continue;
                }
                String attr = transferProductEnum.getAttr();
                switch (transferProductEnum) {
                    case PRODUCT:
                        json.put(attr, transferProductEntity.getProductId());
                        break;
                    case NUM:
                        json.put(attr, transferProductEntity.getProductNum());
                        break;
                    case STOCK:
                        json.put(attr, stock);
                        break;
                    case MEMO:
                        json.put(attr, StringUtil.isNotEmpty(productBaseInfoEntity.getMemo()) ? productBaseInfoEntity.getMemo():transferProductEntity.getMemo());
                        break;
                    case UNIT:
                        json.put(attr, transferProductEntity.getProductUnit());
                        break;
                    case OUTSTOCK_NUM:
                        json.put(attr,transferProductEntity.getOutstockNum());
                        break;
                    case INSTOCK_NUM:
                        json.put(attr,transferProductEntity.getInstockNum());
                        break;
                    case WAIT_INSTOCK_NUM:
                        json.put(attr,Arith.sub(transferProductEntity.getOutstockNum(),transferProductEntity.getInstockNum()));
                        break;
                    case TRANSFER_STATUS:
                        if (transferProductEntity.getOutstockNum() > 0) {
                            if (transferProductEntity.getInstockNum() > 0){
                                if (Objects.equals(transferProductEntity.getInstockNum(), transferProductEntity.getOutstockNum())) {
                                    json.put(attr, I18nMessageUtil.getMessage(I18nStringConstant.STOCK_IN_ALL));
                                } else {
                                    json.put(attr, I18nMessageUtil.getMessage(I18nStringConstant.PARTIAL_WAREHOUSING));
                                }
                            }else {
                                json.put(attr, InOutStockStatusEnum.UN_INSTOCK.getName());
                            }
                        } else {
                            json.put(attr, InOutStockStatusEnum.UN_OUTSTOCK.getName());
                        }
                        break;
                    default:
                        break;
                }
            }
            if (Objects.equals(json.getDouble(SelectProductEnum.GUARANTEE_PERIOD.getAttr()), 0D)) {
                if (Objects.equals(json.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()), 0L) || Objects.isNull(json.get(SelectProductEnum.PRODUCE_DATE.getAttr()))) {
                    json.remove(SelectProductEnum.GUARANTEE_PERIOD.getAttr());
                }
            }
            json.put(BusinessConstant.PRODUCT_SUB_ID, transferProductEntity.getId());
            productArray.add(json);
        }
        detailProductVO.setProductDataArr(productArray);
        return detailProductVO;
    }

    @Override
    public void formatProduct4Show2(Long dataId, String corpid, JSONObject data, Boolean forProcess, Integer operate, UpdateDataTypeEnum updateDataTypeEnum) throws XbbException {
        transferModel.formatProduct4Show2(dataId, corpid, data, forProcess, operate, updateDataTypeEnum);
    }

    @Override
    public JSONObject formatSingleProduct(TransferProductEntity transferProductEntity, ProductBaseInfoEntity productBaseInfoEntity) {
        return transferModel.formatSingleProduct(transferProductEntity, productBaseInfoEntity);
    }

    @Override
    public boolean judgeTransferAllInBound(Long instockId, Long outstockId, Long refId, String corpid, List<ProductSavePojo> productSavePojoList) throws XbbException {
       return transferHelp.judgeTransferAllInBound(instockId, outstockId, refId, corpid, productSavePojoList);
    }

    @Override
    public void updateTransferOutstockNum(List<Long> refIds, String corpid, List<ProductSavePojo> productSavePojoList,Boolean isSave) throws XbbException {
        transferHelp.updateTransferOutstockNum(refIds, corpid, productSavePojoList, isSave);
    }

    @Override
    public void updateTransferInstockNum(List<Long> refIds, String corpid, List<ProductSavePojo> productSavePojoList, List<InstockProductEntity> instockProductEntities) throws XbbException {
        transferHelp.updateTransferInstockNum(refIds, corpid, productSavePojoList, instockProductEntities);
    }

    @Override
    public ChangeDocumentStatusSaveVO changeDocumentStatus(ChangeDocumentStatusSaveDTO changeDocumentStatusSaveDTO) throws XbbException {
        ChangeDocumentStatusSaveVO changeDocumentStatusSaveVO = new ChangeDocumentStatusSaveVO();
        try {
            Boolean isOpen = changeDocumentStatusSaveDTO.getIsOpen();
            String corpid = changeDocumentStatusSaveDTO.getCorpid();
            Long transferId = changeDocumentStatusSaveDTO.getDataId();
            Integer businessType = changeDocumentStatusSaveDTO.getBusinessType();
            TransferEntityExt transferEntityExt = transferModel.getByKey(transferId, corpid);
            if (Objects.isNull(transferEntityExt)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, MessageConstant.FORM_DATA_NOT_EXIST);
            }
            JSONObject transferEntityExtData = transferEntityExt.getData();
            //如果是开启调拨单
            if (isOpen) {
                Integer allInBound = transferEntityExtData.getInteger(TransferEnum.ALL_IN_BOUND.getAttr());
                if (Objects.isNull(allInBound)) {
//                    老数据逻辑
                        Integer outstockId = transferEntityExtData.getInteger(TransferEnum.OUTSTOCK_ID.getAttr());
                        Integer instockId = transferEntityExtData.getInteger(TransferEnum.INSTOCK_ID.getAttr());
                        if (Objects.isNull(outstockId) || outstockId < 1) {
                            transferEntityExtData.put(TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.UNTRANSFORMED.getCode());
                        }else if (Objects.isNull(instockId) || instockId < 1){
                            transferEntityExtData.put(TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.UNRECEIVED.getCode());
                        }else {
                            transferEntityExtData.put(TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.TRANSFERRED.getCode());
                        }
                }else {
                    //如果入库完毕
                    if (Objects.equals(allInBound,AllInBoundEnum.ALL_IN.getCode())) {
                        transferEntityExtData.put(TransferEnum.TRANSFER_STATUS.getAttr(),TransferNewStatusEnum.TRANSFERRED.getCode());
                    }else {
                        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
                        boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                        boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.TYPE), OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode()));
                        boolQueryBuilder.filter(termQuery(OutstockEnum.getEsAttr4Keyword(OutstockEnum.REF_ID), transferId));
                        boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
                        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_OUTSTOCK.getType()));
                        sourceBuilder.query(boolQueryBuilder);
                        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 1, 1);
                        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_OUTSTOCK.getIndex());
                        searchRequest.source(sourceBuilder);
                        XbbAggregatedPage<PaasFormDataEntityExt> entities = xbbElasticsearchRestTemplate.queryForPages(pageRequest,searchRequest, PaasFormDataEntityExt.class);


                        //先查询出库单，如果没有则确定是未出库状态
                        if (entities.getTotalElements() < 1){
                            transferEntityExtData.put(TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.UNTRANSFORMED.getCode());
                        }else {
                            //查询入库单
                            sourceBuilder = new SearchSourceBuilder();
                            boolQueryBuilder = new BoolQueryBuilder();
                            boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                            boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.TYPE), InstockTypeEnum.TRANSFER_INSTOCK.getCode()));
                            boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.REF_ID), transferId));
                            boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
                            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_INSTOCK.getType()));
                            sourceBuilder.query(boolQueryBuilder);
                            PageRequest pageRequest1 = EsUtil.setPage(sourceBuilder, 1, 1);
                            SearchRequest searchRequest1 = new SearchRequest(IndexTypeEnum.IDX_SAAS_INSTOCK.getIndex());
                            searchRequest1.source(sourceBuilder);
                            XbbAggregatedPage<PaasFormDataEntityExt> entities1 = xbbElasticsearchRestTemplate.queryForPages(pageRequest1,searchRequest1, PaasFormDataEntityExt.class);
                            if (entities1.getTotalElements() < 1) {
                                transferEntityExtData.put(TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.UNRECEIVED.getCode());
                            }else {
                                transferEntityExtData.put(TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.DELIVERED.getCode());
                            }
                        }
                    }

                }
            }else {
                transferEntityExtData.put(TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.CLOSED.getCode());
            }
            transferModel.update(transferEntityExt);
            //添加关闭和开启调拨的按钮
            String transferStatus = FastJsonHelper.getStringOrDefaultFromFormData(transferEntityExtData, TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.UNTRANSFORMED.getCode());
            //如果全部入库，则没有开启关闭按钮
            if (!Objects.equals(transferStatus, TransferNewStatusEnum.TRANSFERRED.getCode())) {
                ButtonPojo buttonPojo = new ButtonPojo();
                if (Objects.equals(transferStatus,TransferNewStatusEnum.CLOSED.getCode())&&changeDocumentStatusSaveDTO.getLoginUser().getPermSet().contains(EnableButtonEnum.TRANSFER_ENBALE.getPermission())) {
                    buttonPojo.setAttr("transfer");
                    buttonPojo.setValue(OperateTypeEnum.ENABLE.getName());
                    buttonPojo.setLinkBusinessType(XbbRefTypeEnum.TRANSFER.getCode());
                    List<ButtonPojo> topRightButton = new ArrayList<>();
                    topRightButton.add(buttonPojo);
                    changeDocumentStatusSaveVO.setTopRightButton(topRightButton);
                }else if (!Objects.equals(transferStatus,TransferNewStatusEnum.CLOSED.getCode())&&changeDocumentStatusSaveDTO.getLoginUser().getPermSet().contains(EnableButtonEnum.TRANSFER_UNBALE.getPermission())){
                    buttonPojo.setAttr("transfer");
                    buttonPojo.setValue(OperateTypeEnum.UNABLE.getName());
                    buttonPojo.setLinkBusinessType(XbbRefTypeEnum.TRANSFER.getCode());
                    List<ButtonPojo> topRightButton = new ArrayList<>();
                    topRightButton.add(buttonPojo);
                    changeDocumentStatusSaveVO.setTopRightButton(topRightButton);
                }
            }
            // 刷新页面saas关联新建工作流
            PaasFormDataEntityExt paasFormDataEntityExt = new PaasFormDataEntityExt();
            BeanUtil.copyProperties(transferEntityExt,paasFormDataEntityExt);
            if (Objects.equals(PlatFormEnum.DINGTALK.getValue(), changeDocumentStatusSaveDTO.getPlatform())) {
                // 设置移动端详情右上角操作
                FormDataGetVO formDataGetVO = new FormDataGetVO();
                mobileDetailService.handelMobileWorkFlow(changeDocumentStatusSaveDTO.getLoginUser(), businessType, formDataGetVO, paasFormDataEntityExt);
                changeDocumentStatusSaveVO.setTopPermissions(formDataGetVO.getTopPermissions());
            }else {
                List<WorkFlowPojo> workFlowPojoList = new ArrayList<>();
                proDetailHandlerHelp.handelDetailWorkFlow(businessType, paasFormDataEntityExt, workFlowPojoList, changeDocumentStatusSaveDTO.getLoginUser());
                changeDocumentStatusSaveVO.setWorkFlowPojoList(workFlowPojoList);
            }
        } catch (Exception e) {
            LOG.error("TransferServiceImpl.changeDocumentStatus 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return changeDocumentStatusSaveVO;
    }

    @Override
    public void updateBatchLabelAttr(AddLabelDTO addLabelDTO, List<PaasFormDataEntityExt> addBatchList, Boolean addOrDelete) throws XbbException {
        TransferUpdateBatchDTO updateBatchDTO = new TransferUpdateBatchDTO();
        BeanUtil.copyProperties(addLabelDTO, updateBatchDTO);
        List<TransferUpdateDTO> updateList = new ArrayList<>();
        addBatchList.forEach(item->{
            TransferUpdateDTO updateDTO= new TransferUpdateDTO();
            updateDTO.setData(item.getData());
            updateDTO.setId(item.getId());
            updateList.add(updateDTO);
        });
        updateBatchDTO.setTransferList(updateList);
        updateBatch(updateBatchDTO);

    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        Long id = saasFormSaveDTO.getNewPaasFormDataEntity().getId();
        JSONObject newData = saasFormSaveDTO.getNewData();
        JSONArray productArray = newData.getJSONArray(TransferEnum.PRODUCTS.getAttr());
        Long intoWarehouseId = FastJsonHelper.getLongOrDefaultFromFormData(newData, TransferEnum.INTO_WAREHOUSE_ID.getAttr(), 0L);
        Long outWarehouseId = FastJsonHelper.getLongOrDefaultFromFormData(newData, TransferEnum.OUT_WAREHOUSE_ID.getAttr(), 0L);
        Long formId = saasFormSaveDTO.getNewPaasFormDataEntity().getFormId();
        Boolean productCanSee = saasFormSaveDTO.getSaasNeedRedundantAttrPoJo().getAttrCanSee(TransferEnum.PRODUCTS.getAttr());
        Boolean hasInOrOut = Objects.isNull(FastJsonHelper.getLongOrDefaultFromFormData(saasFormSaveDTO.getNewData(),TransferEnum.INSTOCK_ID.getAttr(),null)) || Objects.isNull(FastJsonHelper.getLongOrDefaultFromFormData(saasFormSaveDTO.getNewData(),TransferEnum.OUTSTOCK_ID.getAttr(),null));
        // 更新调拨单关联产品
        if (saasFormSaveDTO.getIsNew() || (productCanSee && !hasInOrOut)){
            saveProductForWorkflow(saasFormSaveDTO.getCorpid(), id, intoWarehouseId, outWarehouseId, productArray, formId, saasFormSaveDTO.getIsNew());
        }
    }

    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        Long id = saasFormSaveDTO.getNewPaasFormDataEntity().getId();
        JSONObject newData = saasFormSaveDTO.getNewData();
        String transferType = FastJsonHelper.getStringOrDefaultFromFormData(newData, TransferEnum.TRANSFER_TYPE.getAttr(), TransferTypeEnum.UNLOCAL_TRANSFER.getCode());
        JSONArray productArray = newData.getJSONArray(TransferEnum.PRODUCTS.getAttr());
        Long intoWarehouseId = FastJsonHelper.getLongOrDefaultFromFormData(newData, TransferEnum.INTO_WAREHOUSE_ID.getAttr(), 0L);
        Long outWarehouseId = FastJsonHelper.getLongOrDefaultFromFormData(newData, TransferEnum.OUT_WAREHOUSE_ID.getAttr(), 0L);
        Long formId = saasFormSaveDTO.getNewPaasFormDataEntity().getFormId();
        Boolean productCanSee = saasFormSaveDTO.getSaasNeedRedundantAttrPoJo().getAttrCanSee(TransferEnum.PRODUCTS.getAttr());
        Boolean hasInOrOut = Objects.isNull(FastJsonHelper.getLongOrDefaultFromFormData(saasFormSaveDTO.getNewData(),TransferEnum.INSTOCK_ID.getAttr(),null)) || Objects.isNull(FastJsonHelper.getLongOrDefaultFromFormData(saasFormSaveDTO.getNewData(),TransferEnum.OUTSTOCK_ID.getAttr(),null));
        // 更新调拨单关联产品
        if (productCanSee && !hasInOrOut) {
            saveProductForWorkflow(saasFormSaveDTO.getCorpid(), id, intoWarehouseId, outWarehouseId, productArray, formId, saasFormSaveDTO.getIsNew());
        }
    }

    /**
     * 新建时格式化解释
     *
     * @param formatExplainDTO 入参
     * @throws XbbException 异常
     */
    @Override
    public void formatAddExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        List<FieldAttrEntity> explainList = formatExplainDTO.getExplainList();
        String corpid = formatExplainDTO.getCorpid();
        String platForm = formatExplainDTO.getPlatform();
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            Integer fieldType = fieldAttrEntity.getFieldType();
            if (Objects.equals(fieldType, FieldTypeEnum.SELECT_PRODUCT.getType())) {
                fieldAttrEntity.setSupportScanning(BasicConstant.ONE);
                explainHelp.formatSelectProductExplains(fieldAttrEntity, XbbRefTypeEnum.TRANSFER, corpid, OperatePageEnum.NEW.getCode(), false);
                if (Objects.equals(platForm, PlatFormEnum.DINGTALK.getValue())) {
                    SaasParticularAttributePoJo saasParticularAttributePoJo = fieldAttrEntity.getSaasParticularAttributePoJo();
                    saasParticularAttributePoJo.setProductRelyAttr(TransferEnum.OUT_WAREHOUSE_ID.getAttr());
                }
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), TransferEnum.MANAGER_NAME.getAttr())) {
                if(fieldAttrEntity.getDefaultAttr() == null || (fieldAttrEntity.getDefaultAttr() != null && fieldAttrEntity.getDefaultAttr().getDefaultList() == null)) {
                    fieldAttrEntity.setDefaultAttr(defaultAttrHelp.setUserDefaultAttrPoJo(formatExplainDTO.getUserId(), formatExplainDTO.getLoginUser().getName(),formatExplainDTO.getLoginUser().getAvatar()));
                }
            }
            if (Objects.equals(fieldAttrEntity.getAttr(), TransferEnum.TRANSFER_TIME.getAttr())) {
                DefaultAttrPoJo defaultAttrPoJo = fieldAttrEntity.getDefaultAttr();
                defaultAttrPoJo.setDefaultType("dateByBackEnd");
                defaultAttrPoJo.setDefaultValue(DateUtil.getTodayInt() + "");
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TransferDeleteBatchVO deleteBatch(TransferDeleteBatchDTO transferDeleteBatchDTO) throws XbbException {
        TransferDeleteBatchVO transferDeleteBatchVO = new TransferDeleteBatchVO();
        try {
            String corpid = transferDeleteBatchDTO.getCorpid();
            List<Long> idList = transferDeleteBatchDTO.getDataIdList();
            Map<String, Object> param = BeanUtil.convertBean2Map(transferDeleteBatchDTO, true);
            param.put("ids", idList);
            param.put("del", DelEnum.NORMAL.getDel());
            List<TransferEntityExt> transferList = transferModel.findEntitys(param);
            List<String> transferSerialNos = new ArrayList<>();
            List<Long> transferIdList = new ArrayList<>();
            // 调拨单删除校验
            //结账内校验
            for (TransferEntityExt transferEntityExt : transferList) {
                JSONObject data = transferEntityExt.getData();
                Long date = data.getLong(TransferEnum.TRANSFER_TIME.getAttr());
                //结账中校验
                String redisHelperValue = paasRedisHelper.getValue(RedisPrefixConstant.SETTLE_ACCOUNTS, corpid);
                if (StringUtil.isNotEmpty(redisHelperValue)) {
                    if (date <= DateTimeUtil.getTodayEndInt(Long.valueOf(redisHelperValue))) {
                        throw new XbbException(SettleAccountErrorCodeEnum.API_ERROR_254007);
                    }
                }
                SettleAccountsEntity accountsEntity = settleAccountsModel.getLastSettleAccounts(corpid);
                //校验日期是否受结账限制
                if (Objects.nonNull(accountsEntity) && Objects.nonNull(accountsEntity.getCheckOutTime())) {
                    if (date <= DateTimeUtil.getTodayEndInt(accountsEntity.getCheckOutTime())) {
                        throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212032);
                    }
                }
            }
            // 序列号关联表单删除校验
            if (CollectionUtils.isNotEmpty(idList)) {
                productSerialService.preCheckDelSerial(idList, corpid, XbbRefTypeEnum.TRANSFER.getCode());
            }
            // 校验调拨单是否关联下游单据【其他出库单】
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            BoolQueryBuilder queryBuilder = boolQuery();
            queryBuilder.filter(termQuery("corpid.keyword", corpid));
            queryBuilder.filter(termQuery("data." + OutstockEnum.TYPE.getAttr(), OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode()));
            queryBuilder.filter(termsQuery("data." + OutstockEnum.REF_ID.getAttr(), idList));
            queryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            // 设置join_field
            queryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_OTHER_OUTSTOCK.getType()));
            searchSourceBuilder.query(queryBuilder);
            List<PaasFormDataEntityExt> entityExts = paasEsModel.list(searchSourceBuilder, IndexTypeEnum.IDX_SAAS_OTHER_OUTSTOCK, Collections.singletonList(OutstockEnum.REF_ID.getAttr()), null, null);
            if (Objects.nonNull(entityExts) && entityExts.size() > 0) {
                entityExts.forEach(item -> {
                    Long transferId = item.getData().getLong(OutstockEnum.REF_ID.getAttr());
                    transferIdList.add(transferId);
                });
                for (TransferEntityExt transferEntityExt : transferList) {
                    if (transferIdList.contains(transferEntityExt.getId())) {
                        transferSerialNos.add(transferEntityExt.getSerialNo());
                    }
                }
                throw new XbbException(InstockErrorCodeEnum.API_ERROR_210032, String.format(InstockErrorCodeEnum.API_ERROR_210032.getMsg(), transferSerialNos.toString()));
            }
            // 校验调拨单是否关联下游单据【其他入库单】
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("data." + InstockEnum.TYPE.getAttr(), InstockTypeEnum.TRANSFER_INSTOCK.getCode()));
            boolQueryBuilder.filter(termsQuery("data." + InstockEnum.REF_ID.getAttr(), idList));
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            // 设置join_field
            queryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_OTHER_INSTOCK.getType()));
            searchSourceBuilder.query(boolQueryBuilder);
            entityExts = paasEsModel.list(searchSourceBuilder, IndexTypeEnum.IDX_SAAS_OTHER_INSTOCK, Collections.singletonList(InstockEnum.REF_ID.getAttr()), null, null);
            if (Objects.nonNull(entityExts) && entityExts.size() > 0) {
                entityExts.forEach(item -> {
                    Long transferId = item.getData().getLong(InstockEnum.REF_ID.getAttr());
                    transferIdList.add(transferId);
                });
                for (TransferEntityExt transferEntityExt : transferList) {
                    if (transferIdList.contains(transferEntityExt.getId())) {
                        transferSerialNos.add(transferEntityExt.getSerialNo());
                    }
                }
                throw new XbbException(InstockErrorCodeEnum.API_ERROR_210031, String.format(InstockErrorCodeEnum.API_ERROR_210031.getMsg(), transferSerialNos.toString()));
            }
            //查询编号
            List<String> no= new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            BoolQueryBuilder builder = boolQuery();
            // 添加corpid,formId,del
            builder.filter(termQuery("corpid.keyword", corpid));
            builder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            builder.filter(termsQuery(StringConstant.DATA_ID, idList));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.SERIALNO.getAlias());
            List<PaasFormDataEntityExt> noList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_TRANSFER, builder, PaasFormDataEntityExt.class, fieldList);
            for(PaasFormDataEntityExt entityExt : noList){
                String sheetNo = entityExt.getSerialNo();
                no.add(sheetNo);
            }

            // TODO 删除权限校验
            // 因为待审批和和审批中的数据不存在表中，所以无需校验待审批和审批中的数据
            // 删除调拨单
            if(!idList.isEmpty()) {
                if(BasicConstant.ONE.equals(transferDeleteBatchDTO.getSingleFlag())
                        && BasicConstant.ONE.equals(idList.size())){
                    transferModel.deleteByKey(idList.get(0),corpid);
                }else {
                    transferModel.deleteBatch(idList, corpid, DelEnum.DELETE.getDel());
                }
                transferDeleteBatchVO.setDeleteIds(idList);
            }
            TransferProductListDTO transferProductListDTO = new TransferProductListDTO();
            BeanUtil.copyProperties(transferDeleteBatchDTO, transferProductListDTO);
            transferProductListDTO.setTransferIdIn(idList);
            TransferProductListVO transferProductListVO = transferProductService.findTransferProductList(transferProductListDTO);
            if (Objects.isNull(transferProductListVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }

            // 删除关联产品
            List<Long> transferProductIdList = new ArrayList<>();
            transferProductListVO.getTransferProductList().forEach((item) -> {
                transferProductIdList.add(item.getId());
            });
            TransferProductDeleteDTO transferProductDeleteDTO = new TransferProductDeleteDTO();
            BeanUtil.copyProperties(transferDeleteBatchDTO, transferProductDeleteDTO);
            transferProductDeleteDTO.setIdList(transferProductIdList);
            // 删除序列号
            productSerialService.deleteSerial(corpid, idList, XbbRefTypeEnum.TRANSFER.getCode());
            transferProductService.deleteBatch(transferProductDeleteDTO);
            // 删除关联产品冗余信息
            List<Long> refIdList = transferProductIdList;
            ProductBaseInfoDeleteBatchDTO productBaseInfoDeleteBatchDTO = new ProductBaseInfoDeleteBatchDTO();
            BeanUtil.copyProperties(transferDeleteBatchDTO, productBaseInfoDeleteBatchDTO);
            productBaseInfoDeleteBatchDTO.setRefIdList(refIdList);
            productBaseInfoDeleteBatchDTO.setRefType(XbbRefTypeEnum.TRANSFER_PRODUCT.getCode());
            productBaseInfoService.deleteBatchByRefId(productBaseInfoDeleteBatchDTO);
            // TODO 删除关联审批记录
            OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
            if (Objects.equals(1, transferDeleteBatchDTO.getIsBusinessRule())) {
                operateTypeEnum = OperateTypeEnum.RULE_DELETE;
            }
            //生成删除日志(区分单个删除和批量删除)
            String userId = transferDeleteBatchDTO.getUserId();
            String userName = transferDeleteBatchDTO.getLoginUserName();
            String nameStr = StringUtils.join(no, "，");
            if(idList.size() > 1){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), userName, XbbRefTypeEnum.TRANSFER.getName(), idList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(TransferEnum.SHEET_NO.getAttrName());
                infoArrPojo.setContent(nameStr);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, OperateModuleTypeEnum.TRANSFER, operateTypeEnum,
                        "", "", memo, transferDeleteBatchDTO.getHttpHeader());
            } else if (Objects.equals(idList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), userName, XbbRefTypeEnum.TRANSFER.getName(), nameStr);
                mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.TRANSFER, operateTypeEnum,
                        idList.get(0).toString(), nameStr, memo, transferDeleteBatchDTO.getHttpHeader());
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("transferServiceImpl.deleteBatch 批量删除出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return transferDeleteBatchVO;
    }

    @Override
    public TransferResetInstockIdVO resetInstockIdByIdIn(TransferResetInstockIdDTO transferResetInstockIdDTO) throws XbbException {
        TransferResetInstockIdVO transferResetInstockIdVO = new TransferResetInstockIdVO();
        try {
            String corpid = transferResetInstockIdDTO.getCorpid();
            List<UpdateDataEntity> list = new ArrayList<>();
            List<Long> idIn = transferResetInstockIdDTO.getIdIn();
            List<Long> delInstockIds = transferResetInstockIdDTO.getDelInstockIds();
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),idIn));
            List<PaasFormDataEntity> paasFormDataEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_TRANSFER, boolQueryBuilder, PaasFormDataEntity.class, Arrays.asList(FieldTypeEnum.DATAID.getAlias(), TransferEnum.getAttrConnectData(TransferEnum.TRANSFER_STATUS)));
            //如果是调拨入库单，则需要判断删除后是部分入库还是未入库的情况了
            HashSet<Long> instockEntities = new HashSet();
            if (Objects.equals(transferResetInstockIdDTO.getAttr(), TransferEnum.INSTOCK_ID.getAttr())) {
                // TODO check 获取调拨单关联的入库单，用于判断当删除了某个调拨入库单后，判断这个调拨单还有没有其他入库单，如果没有了就是未入库，如果还有就是部分入库。那么这里获取入库单的时候要不要包含审批中的呢
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword",corpid))
                        .filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()))
                        .filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.TYPE),InstockTypeEnum.TRANSFER_INSTOCK.getCode()))
                        .mustNot(termsQuery(FieldTypeEnum.DATAID.getAlias(), delInstockIds))
                        .filter(termsQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.REF_ID),idIn));
                List<PaasFormDataEntity> instockDataEntities = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_INSTOCK, boolQueryBuilder, PaasFormDataEntity.class, Arrays.asList(FieldTypeEnum.DATAID.getAlias(), InstockEnum.getAttrConnectData(InstockEnum.REF_ID)));
                instockDataEntities.forEach(item -> {
                    instockEntities.add(item.getData().getLong(InstockEnum.REF_ID.getAttr()));
                });
            }
            for (PaasFormDataEntity item : paasFormDataEntityList) {
                Long transferId = item.getDataId();
                String transferStatus = FastJsonHelper.getStringOrDefaultFromFormData(item.getData(), TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.UNTRANSFORMED.getCode());
                JSONObject updateData = new JSONObject();
                updateData.put(transferResetInstockIdDTO.getAttr(),0);
                //首先需要判断调拨状态是否是已关闭状态
                if (!Objects.equals(transferStatus, TransferNewStatusEnum.CLOSED.getCode())) {
                    //分删除出库单和入库单处理
                    if (Objects.equals(transferResetInstockIdDTO.getAttr(), TransferEnum.OUTSTOCK_ID.getAttr())) {
                        updateData.put(TransferEnum.TRANSFER_STATUS.getAttr(),TransferNewStatusEnum.UNTRANSFORMED.getCode());
                    }else {
                        updateData.put(TransferEnum.TRANSFER_STATUS.getAttr(),TransferNewStatusEnum.UNRECEIVED.getCode());
                        if (instockEntities.contains(transferId)) {
                            updateData.put(TransferEnum.TRANSFER_STATUS.getAttr(),TransferNewStatusEnum.DELIVERED.getCode());
                        }
                    }
                }
                updateData.put(TransferEnum.STATUS.getAttr(),TransferStatusEnum.WAIT_OUT_INSTOCK.getCode().toString());
                updateData.put(TransferEnum.ALL_IN_BOUND.getAttr(), AllInBoundEnum.NON_IN.getCode());
                list.add(ExplainUtil.getUpdateData(transferId, updateData, corpid));
            };
            transferModel.updateBatch(list, corpid);
        } catch (Exception e) {
            LOG.error("transferServiceImpl.resetInstockIdByIdIn 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return transferResetInstockIdVO;
    }

    @Override
    public void dataConsistencyUpdateWarehouse(String corpid, Long dataId, String name) throws XbbException {
        try {
            BoolQueryBuilder filter = boolQuery()
                    .filter(termQuery("corpid.keyword", corpid))
                    .filter(termQuery("del", 0));
            BoolQueryBuilder filter1 = boolQuery()
                    .filter(termQuery("data." + TransferEnum.INTO_WAREHOUSE_ID.getAttr() + ".keyword", dataId));
            BoolQueryBuilder filter2 = boolQuery()
                    .filter(termQuery("data." + TransferEnum.OUT_WAREHOUSE_ID.getAttr() + ".keyword", dataId));
            filter.should(filter1);
            filter.should(filter2);
            filter.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            List<PaasFormDataEntityExt> esEntities = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_TRANSFER, filter, PaasFormDataEntityExt.class, fieldList);
            Set<Long> ids = new HashSet<>();
            for (PaasFormDataEntityExt esEntity : esEntities) {
                ids.add(esEntity.getDataId());
            }

            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", ids);
            param.put("del", 0);
            List<TransferEntityExt> transferEntityExts = transferModel.findEntitys(param);
            if (Objects.nonNull(transferEntityExts) && !transferEntityExts.isEmpty()) {
                List<TransferUpdateDTO> transferUpdateDTOList = new ArrayList<>();
                for (TransferEntityExt entityExt : transferEntityExts) {
                    JSONObject data = entityExt.getData();
                    Long inWarehouseId = data.getLong(TransferEnum.INTO_WAREHOUSE_ID.getAttr());
                    Long outWarehouseId = data.getLong(TransferEnum.OUT_WAREHOUSE_ID.getAttr());
                    JSONObject updateData = new JSONObject();
                    if (Objects.equals(inWarehouseId, dataId)) {
                        updateData.put(TransferEnum.INTO_WAREHOUSE_ID_LINKED_TEXT.getAttr(), name);
                    } else if (Objects.equals(outWarehouseId, dataId)) {
                        updateData.put(TransferEnum.OUT_WAREHOUSE_ID_LINKED_TEXT.getAttr(), name);
                    }
                    TransferUpdateDTO transferUpdateDTO = new TransferUpdateDTO();
                    transferUpdateDTO.setId(entityExt.getId());
                    transferUpdateDTO.setData(updateData);
                    transferUpdateDTOList.add(transferUpdateDTO);
                }
                TransferUpdateBatchDTO transferUpdateBatchDTO = new TransferUpdateBatchDTO();
                transferUpdateBatchDTO.setCorpid(corpid);
                transferUpdateBatchDTO.setTransferList(transferUpdateDTOList);
                updateBatch(transferUpdateBatchDTO);
            }
        } catch (Exception e) {
            LOG.error("TransferServiceImpl.dataConsistencyUpdateWarehouse 出错， corpid=" + corpid + "  warehouseId=" + dataId + "  warehouseName=" + name, e);
        }
    }

    /**
     * 获取采购合同产品
     *
     * @param businessProductListDTO 入参
     * @author long.rao
     * @date 2019-08-28 10:24
     **/
    @Override
    public ProductSummaryVO summaryProductList(BusinessProductListDTO businessProductListDTO) throws XbbException {
        // 获取参数
        String corpid = businessProductListDTO.getCorpid();
        Long dataId = businessProductListDTO.getDataId();
        TransferEntityExt transferEntityExt = transferModel.getByKey(dataId, corpid);

        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, corpid);
        modelMap.put(ParameterConstant.TRANSFER_ID, dataId);
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        modelMap.put("columns", "product_num,business_num");
        List<TransferProductEntity> transferProductEntities = transferProductModel.findEntitys(modelMap);

        ProductSummaryVO businessProductListVO = new ProductSummaryVO();

        Double num = 0D;
        for (TransferProductEntity purchaseProduct : transferProductEntities) {
            Double productNum = purchaseProduct.getProductNum() != null ? purchaseProduct.getProductNum(): 0D;
            num = Arith.add(num, purchaseProduct.getBusinessNum() != null ? purchaseProduct.getBusinessNum() : productNum);
        }
        Integer productSize = transferProductEntities.size();
        String summaryInfo = String.format(I18nMessageUtil.getMessage(StringConstant.PRODUCTS_TYPE_NUM), productSize, Arith.doubleToBigDecimal(num));
        businessProductListVO.setSummaryInfo(summaryInfo);
        //添加关闭和开启调拨的按钮
        JSONObject data = transferEntityExt.getData();
        String transferStatus = FastJsonHelper.getStringOrDefaultFromFormData(data, TransferEnum.TRANSFER_STATUS.getAttr(), TransferNewStatusEnum.UNTRANSFORMED.getCode());
        if (!Objects.equals(transferStatus, TransferNewStatusEnum.TRANSFERRED.getCode()) && num != 0D) {
            ButtonPojo buttonPojo = new ButtonPojo();
            if (Objects.equals(transferStatus, TransferNewStatusEnum.CLOSED.getCode()) && businessProductListDTO.getLoginUser().getPermSet().contains(EnableButtonEnum.TRANSFER_ENBALE.getPermission())) {
                buttonPojo.setAttr("transfer");
                buttonPojo.setValue(OperateTypeEnum.ENABLE.getName());
                buttonPojo.setLinkBusinessType(XbbRefTypeEnum.TRANSFER.getCode());
                List<ButtonPojo> topRightButton = new ArrayList<>();
                topRightButton.add(buttonPojo);
                businessProductListVO.setTopRightButton(topRightButton);
            }else if (!Objects.equals(transferStatus, TransferNewStatusEnum.CLOSED.getCode()) && businessProductListDTO.getLoginUser().getPermSet().contains(EnableButtonEnum.TRANSFER_UNBALE.getPermission())){
                buttonPojo.setAttr("transfer");
                buttonPojo.setValue(OperateTypeEnum.UNABLE.getName());
                buttonPojo.setLinkBusinessType(XbbRefTypeEnum.TRANSFER.getCode());
                List<ButtonPojo> topRightButton = new ArrayList<>();
                topRightButton.add(buttonPojo);
                businessProductListVO.setTopRightButton(topRightButton);
            }
        }
        return businessProductListVO;
    }

    @Override
    public void updateBatchByBusinessRule(TransferUpdateByBusinessRuleDTO transferUpdateByBusinessRuleDTO) throws XbbException {
        try {
            String corpid = transferUpdateByBusinessRuleDTO.getCorpid();
            List<PaasFormDataEntityExt> formDataList = transferUpdateByBusinessRuleDTO.getFormDataList();
            List<UpdateDataEntity> updateList = ExplainUtil.getUpdateValueByBusinessRule(transferUpdateByBusinessRuleDTO.getFormDataList(), corpid, transferUpdateByBusinessRuleDTO.getOperations());

            if (!updateList.isEmpty()) {
                transferModel.updateBatch(updateList, corpid);
                RuleBusinessLogDTO businessLogDTO = new RuleBusinessLogDTO();
                BeanUtil.copyProperties(transferUpdateByBusinessRuleDTO, businessLogDTO);
                businessLogDTO.setFormDataList(formDataList);
                ruleBusinessLogger.writeLog(businessLogDTO, updateList);
            }
        } catch (Exception e) {
            LOG.error("outstockService.updateFormDataByBusinessRule根据业务规则更新数据出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void formatBatchExplain(List<FieldAttrEntity> fieldAttrEntityList, String enable) {
        String attr = TransferEnum.PRODUCTS.getAttr();
        BatchSeqExplainHelp.getInstance().formatExplain4BatchAffectProductAttr(fieldAttrEntityList, enable, attr);
    }


    @Override
    public void formatBatchOrSeqExplain(List<FieldAttrEntity> fieldAttrEntityList, String enable, String alias) {
        if (CompanyConfigEnum.ENABLE_BATCH_SHELF_MANAGEMENT.getAlias().equals(alias)) {
            formatBatchExplain(fieldAttrEntityList, enable);
        }
    }
}
